不难的线性 DP。
考虑 fa,b,c,df_{a,b,c,d}fa,b,c,d 表示用了 aaa 张爬行 111 格的牌,bbb 张爬行 222 格的牌,以此类推。那么答案就是 fca,cb,cc,cdf_{ca,cb,cc,cd}fca,cb,cc,cd,其中这四个数分别是四种牌的数量。至于状态转移方程?也简单,从当前状态中任意删掉一张牌,然后在四种情况中取最大值即可。注意如果某种牌目前一张都没用,那么是不计算他的。整体方程较长,可以看代码。
时间复杂度为 O(n4)O(n^4)O(n4),而且最劣情况下运算量也大约是 n4256\dfrac{n^4}{256}256n4,实际上一般情况完全比最劣情况的运算量还要少,因此可以通过。
#include <bits/stdc++.h>
using namespace std;
int f[41][41][41][41];
int a[355];
int main() {
int n,m; cin >> n >> m;
int sa = 0,sb = 0,sc = 0,sd = 0;
for(int i = 1;i <= n;i++) {
cin >> a[i];
}
for(int i = 1,x;i <= m;i++) {
cin >> x;
if(x == 1) sa++;
if(x == 2) sb++;
if(x == 3) sc++;
if(x == 4) sd++;
}
f[0][0][0][0] = a[1];
for(int i = 0;i <= sa;i++) {
for(int j = 0;j <= sb;j++) {
for(int k = 0;k <= sc;k++) {
for(int l = 0;l <= sd;l++) {
if(i) f[i][j][k][l] = max(f[i][j][k][l],f[i-1][j][k][l]+a[i+2*j+3*k+4*l+1]);
if(j) f[i][j][k][l] = max(f[i][j][k][l],f[i][j-1][k][l]+a[i+2*j+3*k+4*l+1]);
if(k) f[i][j][k][l] = max(f[i][j][k][l],f[i][j][k-1][l]+a[i+2*j+3*k+4*l+1]);
if(l) f[i][j][k][l] = max(f[i][j][k][l],f[i][j][k][l-1]+a[i+2*j+3*k+4*l+1]);
}
}
}
}
cout << f[sa][sb][sc][sd] << endl;
return 0;
}

537

被折叠的 条评论
为什么被折叠?



