http://codevs.cn/problem/1068/
我的做法是用四维数组dp[50][50][50][50],dp[a][b][c][d]记录的是当剩下a个一的卡片,b个二的卡片,c个三的卡片,d个四的卡片时,最大的得分。
用vector维护到达每个点时的所有状态,所以我这个做法是完全暴力的做法优化而来的。看代码
#include<bits/stdc++.h> #define pb push_back using namespace std; const int maxn = 350; struct node { int a,b,c,d; int ans; }ok; vector<node>V[maxn]; int s[maxn],b[5],dp[40][40][40][40]; int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { for(int i=0;i<n;i++) V[i].clear(); for(int i=0;i<n;i++) scanf("%d",&s[i]); memset(b,0,sizeof(b)); for(int i=1;i<=m;i++) { scanf("%d",&b[0]); b[b[0]]++; } memset(dp,-1,sizeof(dp)); ok.ans = s[0],ok.a = b[1],ok.b = b[2],ok.c = b[3],ok.d = b[4]; V[0].pb(ok); dp[b[1]][b[2]][b[3]][b[4]] = s[0]; for(int i=1;i<n;i++) { for(int j=1;j<=4 && i-j>=0;j++) { for(int k=0;k<V[i-j].size();k++) { ok = V[i-j][k]; if(j==1 && ok.a<=0 ) continue; if(j==2 && ok.b<=0 ) continue; if(j==3 && ok.c<=0 ) continue; if(j==4 && ok.d<=0 ) continue; if(dp[ok.a][ok.b][ok.c][ok.d]<=ok.ans) { switch(j) { case 1:ok.a--;break; case 2:ok.b--;break; case 3:ok.c--;break; case 4:ok.d--;break; } ok.ans+=s[i]; if(dp[ok.a][ok.b][ok.c][ok.d]<ok.ans) { V[i].pb(ok); dp[ok.a][ok.b][ok.c][ok.d]=ok.ans; } } } } } printf("%d\n",dp[0][0][0][0]); } return 0; }后来知道网上有种非常暴力的,直接枚举所有a,b,c,d四种卡片,那种做法比我的快多了。 我怎么就没想到呢!!!!