传送门
这道题在当年应该是一道中高档的题,如今,呵呵,只能算得上签到题了吧!
这显然是dp。
我们弄一个数组f[i][j][k][l],它表示当我们用i张1,j张2,k张3,l张4的卡片时,我们得到的最大分数。
怎么想到的?
你把页面翻到最小面,你就会看见这两行字,没错,这绝对是暗示。
那这样有什么好处?
我们可以快速定位当前到了哪一个格子,因为我们已经知道用了哪些卡片。
而且我们知道这样可以避免因为卡片顺序带来的错误。
代码如下(转移方程自己看):
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int score[355];
int vis[10];
int z;
int f[45][45][45][45];
int res;
int main(){
res=-1;
memset(vis,0,sizeof(vis));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&score[i]);
}
for(int i=0;i<m;i++){
scanf("%d",&z);
vis[z]++;
}
memset(f,-1,sizeof(f));
f[0][0][0][0]=score[1];
for(int i=0;i<=vis[1];i++){
for(int j=0;j<=vis[2];j++){
for(int k=0;k<=vis[3];k++){
for(int l=0;l<=vis[4];l++){
int now=i+2*j+3*k+4*l+1;
if(now<=n){
int& ans=f[i][j][k][l];
if(i>0&&f[i-1][j][k][l]>=0){
ans=max(ans,f[i-1][j][k][l]+score[now]);
}
if(j>0&&f[i][j-1][k][l]>=0){
ans=max(ans,f[i][j-1][k][l]+score[now]);
}
if(k>0&&f[i][j][k-1][l]>=0){
ans=max(ans,f[i][j][k-1][l]+score[now]);
}
if(l>0&&f[i][j][k][l-1]>=0){
ans=max(ans,f[i][j][k][l-1]+score[now]);
}
res=max(res,ans);
}
}
}
}
}
printf("%d",res);
return 0;
}