AcWing 312. 乌龟棋(Java 线性DP 四维费用)
原题链接
简单
作者:
Limited
,
2021-03-13 17:31:18
,
所有人可见
,
阅读 361
要点
- 卡片有四种,即每次可以走的可能步数有四种,且每个卡片都会被使用到,但使用的顺序不一定
- $f(a,b,c,d)$表示“使用了$a$种$A$卡、$b$种$B$卡、$c$种$C$卡、$d$种$D$卡的选法集合”,属性:分值$Max$
- 状态计算
- 对于每一种$abcd$的选法,到达的格子(从1计数)为$step = 1 + a\*1 + b\*2 + c\*3 + d\*4$,该格的分值为$w[step]$。而根据最后一次选用的卡片种类不同,可以分为四种情况,其中
- 以$A$卡结尾,$f(a,b,c,d)=f(a-1,b,c,d) + w[step]$
- 以$B$卡结尾,$f(a,b,c,d)=f(a,b-1,c,d) + w[step]$
- 以$C$卡结尾,$f(a,b,c,d)=f(a,b,c-1,d) + w[step]$
- 以$D$卡结尾,$f(a,b,c,d)=f(a,b,c,d-1) + w[step]$
- 取四种情况等达到的最大分值即为最优解
- 注意当前状态在起点时($a=b=c=d=0$),各种卡都没有也不能使用,但此时分支应为$w[1]$
代码
import java.util.*;
import java.lang.*;
public class Main {
static Scanner scanner = new Scanner(System.in);
static int n, m;
static int[] g = new int[355];
static int[][][][] f = new int[41][41][41][41];
public static void main(String[] args) {
n = scanner.nextInt();
m = scanner.nextInt();
for (int i = 1; i <= n; i++) g[i] = scanner.nextInt();
int[] cnt = new int[5];
for (int i = 1; i <= m; i++) cnt[scanner.nextInt()]++;
for (int a = 0; a <= cnt[1]; a++)
for (int b = 0; b <= cnt[2]; b++)
for (int c = 0; c <= cnt[3]; c++)
for (int d = 0; d <= cnt[4]; d++) {
int w = g[1 + a + b * 2 + c * 3 + d * 4], maxv = w;
if (a > 0) maxv = Math.max(maxv, f[a - 1][b][c][d] + w);
if (b > 0) maxv = Math.max(maxv, f[a][b - 1][c][d] + w);
if (c > 0) maxv = Math.max(maxv, f[a][b][c - 1][d] + w);
if (d > 0) maxv = Math.max(maxv, f[a][b][c][d - 1] + w);
f[a][b][c][d] = maxv;
}
System.out.println(f[cnt[1]][cnt[2]][cnt[3]][cnt[4]]);
}
}