题解[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;
}

完结撒花❀

posted @ 2021-02-25 15:18  xxbbkk  阅读(95)  评论(0编辑  收藏  举报