记忆化搜索
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int num[5],a0[400];
int dp[40][40][40][40],ans=0;
int n,m;
int dfs(int x,int a,int b,int c,int d)
{
if(x==n){
return 0;
}
if(a) dp[a][b][c][d]=max(dp[a][b][c][d],dp[a-1][b][c][d]?dp[a-1][b][c][d]+a0[x+1]:dfs(x+1,a-1,b,c,d)+a0[x+1]);
if(b) dp[a][b][c][d]=max(dp[a][b][c][d],dp[a][b-1][c][d]?dp[a][b-1][c][d]+a0[x+2]:dfs(x+2,a,b-1,c,d)+a0[x+2]);
if(c) dp[a][b][c][d]=max(dp[a][b][c][d],dp[a][b][c-1][d]?dp[a][b][c-1][d]+a0[x+3]:dfs(x+3,a,b,c-1,d)+a0[x+3]);
if(d) dp[a][b][c][d]=max(dp[a][b][c][d],dp[a][b][c][d-1]?dp[a][b][c][d-1]+a0[x+4]:dfs(x+4,a,b,c,d-1)+a0[x+4]);
return dp[a][b][c][d];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a0[i]);
for(int i=1;i<=m;i++){
int x;
scanf("%d",&x);
num[x]++;
}
ans=dfs(1,num[1],num[2],num[3],num[4])+a0[1];
printf("%d",ans);
return 0;
}
dp
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int num[5],a0[400];
int dp[40][40][40][40],ans=0;
int n,m;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a0[i]);
for(int i=1;i<=m;i++){
int x;
scanf("%d",&x);
num[x]++;
}
dp[0][0][0][0]=a0[1];//都用0张牌时,分数为a[1]
int a=num[1],b=num[2],c=num[3],d=num[4];
for(int i1=0;i1<=a;i1++)
for(int i2=0;i2<=b;i2++)
for(int i3=0;i3<=c;i3++)
for(int i4=0;i4<=d;i4++)
{
int x=0,step=i1+i2*2+i3*3+i4*4+1;
if(i1) x=max(x,dp[i1-1][i2][i3][i4]);
if(i2) x=max(x,dp[i1][i2-1][i3][i4]);
if(i3) x=max(x,dp[i1][i2][i3-1][i4]);
if(i4) x=max(x,dp[i1][i2][i3][i4-1]);
dp[i1][i2][i3][i4]=x+a0[step];//+a0[step]移到max里面 不可以 会把dp[0][0][0][0]重新赋值为零 若要移,就需要将x赋值为a0[1];
}
printf("%d",dp[a][b][c][d]);
return 0;
}