【题解】
一题比较容易想到的动态规划
刚开始是想到f[i][l1][l2][l3][l4]表示走到i还剩下l1张‘1’,l2张‘2’,l3张‘3’,l4张‘4’的最大分数 算一下时间复杂度发现只能过50分
后来发现走到哪可以用牌的剩余数表示 所以就减少了i这一维
详见代码(注释掉的为50分的)
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cstdio>
#include <queue>
#include <ctime>
#include <cmath>
#include <vector>
using namespace std;
int i,j,r,t,m,n,k[5],l[5],d,p;
int a[500],f[41][41][41][41];
int main()
{
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++) scanf("%d",&a[i]);
for (i=1;i<=m;i++)
{
scanf("%d",&t);k[t]++;
}
/* f[1][k[1]][k[2]][k[3]][k[4]]=a[1];
for (i=2;i<=n;i++)
for (l[4]=k[4];l[4]>=0;l[4]--)
if ((k[4]-l[4])*4<=i)
for (l[3]=k[3];l[3]>=0;l[3]--)
if ((k[3]-l[3])*3+(k[4]-l[4])*4<=i)
for (l[2]=k[2];l[2]>=0;l[2]--)
if ((k[2]-l[2])*2+(k[3]-l[3])*3+(k[4]-l[4])*4<=i)
for (l[1]=k[1];l[1]>=0;l[1]--)
if ((k[1]-l[1])*1+(k[2]-l[2])*2+(k[3]-l[3])*3+(k[4]-l[4])*4<=i)
{
f[i%5][l[1]][l[2]][l[3]][l[4]]=0;
if (l[1]!=k[1])
f[i%5][l[1]][l[2]][l[3]][l[4]]=max(f[(i-1)%5][l[1]+1][l[2]][l[3]][l[4]],f[i%5][l[1]][l[2]][l[3]][l[4]]);
if (l[2]!=k[2])
f[i%5][l[1]][l[2]][l[3]][l[4]]=max(f[(i-2)%5][l[1]][l[2]+1][l[3]][l[4]],f[i%5][l[1]][l[2]][l[3]][l[4]]);
if (l[3]!=k[3])
f[i%5][l[1]][l[2]][l[3]][l[4]]=max(f[(i-3)%5][l[1]][l[2]][l[3]+1][l[4]],f[i%5][l[1]][l[2]][l[3]][l[4]]);
if (l[4]!=k[4])
f[i%5][l[1]][l[2]][l[3]][l[4]]=max(f[(i-4)%5][l[1]][l[2]][l[3]][l[4]+1],f[i%5][l[1]][l[2]][l[3]][l[4]]);
f[i%5][l[1]][l[2]][l[3]][l[4]]+=a[i];
}
else break;
else break;
else break;
else break;
printf("%d",f[n%5][0][0][0][0]);*/
f[0][0][0][0]=a[1];
for (i=0;i<=k[1];++i)
for (j=0;j<=k[2];++j)
for (t=0;t<=k[3];++t)
for (d=0;d<=k[4];++d)
{
p=i+j*2+t*3+d*4+1;
if (i) f[i][j][t][d]=max(f[i][j][t][d],f[i-1][j][t][d]+a[p]);
if (j) f[i][j][t][d]=max(f[i][j][t][d],f[i][j-1][t][d]+a[p]);
if (t) f[i][j][t][d]=max(f[i][j][t][d],f[i][j][t-1][d]+a[p]);
if (d) f[i][j][t][d]=max(f[i][j][t][d],f[i][j][t][d-1]+a[p]);
}
printf("%d\n",f[k[1]][k[2]][k[3]][k[4]]);
}