题解[UVA10559 Blocks]
题目描述
有 \(n\) 个带有颜色的方块,每消除一段长度为\(x\)的连续的相同颜色的方块可以得到 \(x^2\) 的分数,让你用一种最优的顺序消除所有方块使得得分最多。
Sol
一道巧妙的区间DP题。
设\(f[i][j][k]\)为区间\([i,j]\)在右边还剩\(k\)个和\(j\)颜色相同的块时的解。
\(sum[j]\)为在\(j\)之后颜色等于\(i\)的个数,用来作为\(k\)的范围。
具体的见代码。
Code
#include<bits/stdc++.h>
#define N (210)
using namespace std;
int T,n,cnt,a[N],sum[N],f[N][N][N];
inline int read(){
int w=0;
char ch=getchar();
while(ch>'9'||ch<'0') ch=getchar();
while(ch>='0'&&ch<='9'){
w=(w<<3)+(w<<1)+(ch^48);
ch=getchar();
}
return w;
}
int main(){
T=read();
while(T--){
memset(f,0,sizeof(f));
memset(sum,0,sizeof(sum));
n=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=n-1;i>=1;i--)
for(int j=i+1;j<=n;j++)
if(a[i]==a[j]) sum[i]++;
for(int i=n;i>=1;i--){
for(int j=i;j<=n;j++){
for(int k=i;k<j;k++){
if(a[k]==a[j]){
for(int p=0;p<=sum[k];p++)
f[i][j][p]=max(f[i][j][p],f[k+1][j-1][0]+f[i][k][p+1]);
//右边的一段连同j用掉p+1个,左边的用0个
//在右边全用完
}
}
for(int p=0;p<=sum[j];p++)
f[i][j][p]=max(f[i][j][p],f[i][j-1][0]+(p+1)*(p+1));
//i到j不用,区间右边用p+1个,用完
//
}
}
printf("Case %d: %d\n",++cnt,f[1][n][0]);
}
return 0;
}