Blocks UVA - 10559
这道题要想dp,主要是难在状态表示吧。
首先,光记录1...i合并不对,这样处理不了12321的问题,所以,要记录l...r合并。
怎么让两段分开的颜色合并呢?
比如1213,如何合并两个1?
把这个颜色保存进状态呗。熟悉dp的人都知道,这时候只要关注一个颜色就好
然后我这样表示状态[l][r][c],将l...r合并后剩下c个r的颜色
但这样表示不好,因为你肯定是将两段颜色合并起来,你把一种颜色的数量叠加上去就好了,不用表示具体还剩几个
这样表示状态:[l][r][c],右边加上c个r的颜色,再将l...r合并
然后状态转移就不难了
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=200+2; int dp[N][N][N]; int cnt[N],a[N]; int dps(int l,int r,int c) { int&ret=dp[l][r][c]; if(ret>=0) return ret; if(l==r) return ret=(c+cnt[l])*(c+cnt[l]); ret=0; for(int k=l;k<r;k++) { ret=max(ret,dps(l,k,0)+dps(k+1,r,c)); if(a[r]==a[k]) ret=max(ret,dps(l,k,c+cnt[r])+dps(k+1,r-1,0)); } return ret; } int main() { int T; cin>>T; for(int t=1;t<=T;t++) { int n,cur=0,v; cin>>n; a[0]=-1; for(int i=1;i<=n;i++) { cin>>v; if(v==a[cur]) cnt[cur]++; else a[++cur]=v, cnt[cur]=1; } memset(dp,0xff,sizeof dp); printf("Case %d: %d\n",t,dps(1,cur,0)); } return 0; }

浙公网安备 33010602011771号