分析:
此题我纠结很久,写不出动态方程,看神人代码以后,用一个三位数组dp[i,j,k],表示从第i个到第j个可以消去的方块个数所能获得的最大值。
那么就有:
dp[i][j][k]=dp[i][r-1][0]+(len[r]+k)^2; len[r]是表示第从r个有连续相同的个数。
代码;
#include<stdio.h>
#include<cstring>
#define Max(a,b) a>b?a:b;
#define N 205
bool vis[N];
int idx;
int a[N],color[N],next[N],len[N];
int dp[N][N][N];
int result()
{ //把dp[N][N][N]放在这里程序崩溃,因为函数里的数组开不下这么大的数值,以后要牢记,这次吃亏了。
memset(dp,0,sizeof(dp));
for(int i=1;i<idx;i++){
for(int L=1;L+i-1<idx;L++){
int r=L+i-1;
for(int k=0;k<=next[r];k++){
dp[L][r][k]=dp[L][r-1][0]+(len[r]+k)*(len[r]+k);
for(int j=r-2;j>=L;j--)
if(color[j]==color[r])
dp[L][r][k]=Max(dp[L][r][k],dp[L][j][len[r]+k]+dp[j+1][r-1][0]);
}
}
}
return dp[1][idx-1][0];
}
int main()
{
int t,tmp,n,res,ca=1,i,j;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
scanf("%d",&a[1]);
idx=res=1;
for(i=2;i<=n;i++){
scanf("%d",&a[i]);
if(a[i]==a[i-1]) res++;
else {
color[idx]=a[i-1];
len[idx++]=res;
res=1;
}
}
color[idx]=a[n];
len[idx++]=res;
memset(vis,0,sizeof(vis));
for(i= idx-1; i >= 1; i--){
if(vis[i]) continue;
next[i] = 0;
tmp = i;
for(j = i-2; j >= 1; j--)
if(color[j] == color[tmp]){
next[j] = next[tmp] + len[tmp];
tmp = j;
vis[j--] =1;
}
}
printf("Case %d: %d\n",ca++,result());
}
}