原题链接:https://www.luogu.org/problem/show?pid=1541
超级暴力的四次方DP。
我们每次的决策是选择爬行卡片来决定乌龟棋的行动,那么好,我们用一个f数组记录使用i张1点数卡,j张2点数卡,k张3点数卡,l张4点数卡所能拿到的最多分数。
那么方程是f[i][j][k][l] =max(f[ i-1 ][ j ][ k ][ l ],f[ i ][ j-1 ][ k ][ l ],f[ i ][ j ][ k-1 ][ l ],f[ i ][ j ][ k ][ l-1 ]) + a[1 + i + j*2 + k*3 + l*4];//为了看起来方便
我们开一个数组记录每个点数的牌一共有多少张,然后从0到这个数枚举,进行转移就好。
我写的方法比较奇怪,我用了一个calc函数来计算转移,因为我发现直接转移数组越界了。。
不过不难理解就是了。
参考代码:
1 #include <iostream> 2 #define maxn 355 3 #define N 55 4 #define check cout << "ok" << endl; 5 using namespace std; 6 int f[N][N][N][N]; 7 int a[maxn]; 8 int n,m,point; 9 int cnta[4]; 10 11 int calc(int x,int y,int z,int w){ 12 int ans; 13 int temp[4]; 14 ans = 0; 15 temp[1] = x; 16 temp[2] = y; 17 temp[3] = z; 18 temp[4] = w; 19 for (int i=1;i<=4;i++){ 20 if ( temp[i] > 0 ){ 21 temp[i]--; 22 if (ans < f[ temp[1] ][ temp[2] ][ temp[3] ][ temp[4] ]) 23 ans = f[ temp[1] ][ temp[2] ][ temp[3] ][ temp[4] ]; 24 temp[i]++; 25 } 26 } 27 return ans; 28 } 29 30 int main(){ 31 cin >> n >> m; 32 for (int i=1;i<=n;i++) 33 cin >> a[i]; 34 for (int i=1;i<=m;i++){ 35 cin >> point; 36 cnta[point]++; 37 } 38 39 f[0][0][0][0] = a[1]; 40 for (int i = 0;i <= cnta[1];i++) 41 for (int j = 0;j <= cnta[2];j++) 42 for (int k = 0; k <= cnta[3];k++) 43 for (int l = 0;l <= cnta[4];l++) 44 if (a[1 + i + j*2 + k*3 + l*4] > 0) 45 f[i][j][k][l] = calc(i,j,k,l) + a[1 + i + j*2 + k*3 + l*4]; 46 47 cout << f[ cnta[1] ][ cnta[2] ][ cnta[3] ][ cnta[4] ] << endl; 48 return 0; 49 }