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\n",t,f[1][n][0]);
    }
    return 0;
}
上一篇:UVA10559 方块消除 Blocks


下一篇:Continuous Same Game (1) 简单的模拟dfs() 很好过