UVA10559 方块消除 Blocks

洛咕

题意:有一排数量为(N(N<=200))的方块,每次可以把连续的相同颜色的区间消除,得到的分数为区间长度的平方,然后左右两边连在一起,问最大分数为多少?

分析:设(f[i][j][k])表示处理区间([i,j]),且在(j)右边有且仅有(k)个和(j)同色的方块,消除所有这些方块的最大分数.考虑如何转移?

1.将(j)(j)右边(k)个和(j)同色的方块一起消掉,(f[i][j][k]=max(f[i][j][k],f[i][j-1][0]+(k+1)^2)

2.在([i,j])中找到一个和(j)同色的点(p),消掉([p+1,j-1])使得(p)(j)相邻,(f[i][j][k]=max(f[i][j][k],f[i][p][k+1]+f[p+1][j-1][0])) (if(color[p]=color[j]))

第一个转移中(j)右边与(j)同色的方块的数量可以直接(n^2)预处理,第二个转移中颜色相等的(p)(j)两个方块直接循环暴力找.总的时间复杂度为(T*n^3.T<=15,n<=200).

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int N=205;
int a[N],sum[N],f[N][N][N];
int main(){
	int T=read();
	for(int t=1;t<=T;++t){
		memset(f,0,sizeof(f));
		memset(sum,0,sizeof(sum));//多组数据一定要记得初始化
		int n=read();
		for(int i=1;i<=n;++i)a[i]=read();
		for(int i=1;i<=n;++i)
			for(int j=i+1;j<=n;++j)
				if(a[j]==a[i])++sum[i];//预处理i右边有多少个与i颜色相同的方块
		for(int i=n;i>=1;--i){//从右边往左边消
			for(int j=i;j<=n;++j){
				for(int k=0;k<=sum[j];++k)
					f[i][j][k]=max(f[i][j][k],f[i][j-1][0]+(k+1)*(k+1));//转移一
				for(int p=i;p<j;++p)//暴力找颜色一样的
					if(a[p]==a[j]){
						for(int k=0;k<=sum[j];++k)
							f[i][j][k]=max(f[i][j][k],f[i][p][k+1]+f[p+1][j-1][0]);//转移二
					}
			}
		}
		printf("Case %d: %d
",t,f[1][n][0]);
	}
    return 0;
}

原文地址:https://www.cnblogs.com/PPXppx/p/11580593.html