该题的难点在于费用的计算,需考虑未来能转移到的所有状态
用dp[l][r][next]表示l到r之间以及r之后与r同色的所有next个方块的最大费用和
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int t,n,a[202],k,cnt; int dp[202][202][202]; struct block{ int x,c; block(){} block(int x,int c):x(x),c(c){} }b[202]; void init(){ k=1,cnt=1; for(int i=1;i<n;i++){ if(a[i]==a[i-1]) cnt++; else{ b[k++]=block(cnt,a[i-1]); cnt=1; } } b[k++]=block(cnt,a[n-1]); } int DP(int l,int r,int next){ if(l>=r) return next*next; if(dp[l][r][next]!=-1) return dp[l][r][next]; int ret=DP(l,r-1,b[r-1].x)+next*next; for(int i=r-1;i>=l;i--){ if(b[i].c==b[r].c){ ret=max(ret,DP(l,i,next+b[i].x)+DP(i+1,r-1,b[r-1].x)); } } //cout<<l<<" "<<r<<" "<<next<<" "<<ret<<endl; return dp[l][r][next]=ret; } int gao(){ memset(dp,-1,sizeof dp); return DP(1,k-1,b[k-1].x); } int main(){ scanf("%d",&t); for(int ca=1;ca<=t;ca++){ scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&a[i]); init(); printf("Case %d: %d\n",ca,gao()); } return 0; }
原文:http://www.cnblogs.com/wonderzy/p/3540671.html