传送门
f
[
i
]
[
j
]
[
k
]
[
l
]
f[i][j][k][l]
f[i][j][k][l]表示用
i
i
i张
1
1
1,
j
j
j张
2
2
2,
k
k
k张
3
3
3,
l
l
l张
4
4
4能凑出的最大贡献。
然后从
f
[
i
−
1
]
[
j
]
[
k
]
[
l
]
,
f
[
i
]
[
j
−
1
]
[
k
]
[
l
]
,
f
[
i
]
[
j
]
[
k
−
1
]
[
l
]
,
f
[
i
]
[
j
]
[
k
]
[
l
−
1
]
f[i-1][j][k][l],f[i][j-1][k][l],f[i][j][k-1][l],f[i][j][k][l-1]
f[i−1][j][k][l],f[i][j−1][k][l],f[i][j][k−1][l],f[i][j][k][l−1]转移过来就行了。
代码:
#include<bits/stdc++.h>
using namespace std;
int f[41][41][41][41],n,m,cnt[5],a[351];
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;++i)a[i]=read();
for(int i=1;i<=m;++i)++cnt[read()];
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 l=0;l<=cnt[4];++l){
int pos=1+i+j*2+k*3+l*4;
if(i)f[i][j][k][l]=max(f[i][j][k][l],f[i-1][j][k][l]+a[pos]);
if(j)f[i][j][k][l]=max(f[i][j][k][l],f[i][j-1][k][l]+a[pos]);
if(k)f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k-1][l]+a[pos]);
if(l)f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k][l-1]+a[pos]);
}
cout<<f[cnt[1]][cnt[2]][cnt[3]][cnt[4]];
return 0;
}