给出
n
≤
350
n\leq350
n≤350个格子,每个格子都有一个权值。起始的位置是
1
1
1,终止的位置是
n
n
n。然后有四张不同的卡片,分别代表走
1
,
2
,
3
,
4
1,2,3,4
1,2,3,4步。保证用完所有的卡片正好走到终点。走到一个位置,得分就会加上这个位置的权值。你选择不同的顺序,得到的总分是不同的。求问得分的最大值。
f
i
,
j
,
k
,
m
f_{i,j,k,m}
fi,j,k,m表示分别用了
i
,
j
,
k
,
m
i,j,k,m
i,j,k,m张卡片得到的最大值。走到的位置由用掉的卡片推出来。然后根据当前用的哪一张卡片转移。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=355;
int cnt[5];
int a[N];
int f[41][41][41][41];
void update(int &x,int y) {
if(y>x) x=y;
}
int getw(int i,int j,int k,int m) {
return a[1+i+2*j+3*k+4*m];
}
int main() {
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=m;i++) {
int x;
scanf("%d",&x);
cnt[x]++;
}
f[0][0][0][0]=a[1];
for(int i=0;i<=cnt[1];i++) {
for(int j=0;j<=cnt[2];j++) {
for(int k=0;k<=cnt[3];k++) {
for(int m=0;m<=cnt[4];m++) {
if(!i&&!j&&!k&&!m) continue;
int W=getw(i,j,k,m);
if(i) update(f[i][j][k][m],f[i-1][j][k][m]+W);
if(j) update(f[i][j][k][m],f[i][j-1][k][m]+W);
if(k) update(f[i][j][k][m],f[i][j][k-1][m]+W);
if(m) update(f[i][j][k][m],f[i][j][k][m-1]+W);
}
}
}
}
printf("%d\n",f[cnt[1]][cnt[2]][cnt[3]][cnt[4]]);
return 0;
}