POJ 1390 Blocks

来源:互联网 发布:域名授权码在哪里 编辑:程序博客网 时间:2024/06/09 14:31

定义f[i][j][ex_len]的状态为,清除i,j之间的木块的最大值,且与j有相邻的且长度为ex_len的木块,那么设j与ex_len连起来的木块为Q。

则有两种选择,一种选择是点掉Q,然后继续点掉i~j-1范围内的木块取最大值,他的值result=dp(i,j-1,0)+(len[j]+ex_len)*(len[j]+ex_len);

另一种选择是从i~j-1中寻找一个与j,ex_len颜色相同的木块k,消除k+1~j-1的木块,这样值为r=dp(i,k,len[j]+ex_len)+dp(k+1.j-1,0)(当然k是在i~j-1中的与j木块相同的木块,需要一个for循环来枚举);

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>const int maxn=200+5;int p[maxn],color[maxn],len[maxn];int f[maxn][maxn][maxn];using namespace std;int dp(int i,int j,int ex_len){    if(f[i][j][ex_len]!=-1) return f[i][j][ex_len];    int result=(len[j]+ex_len)*(len[j]+ex_len);    if(i==j) return result;    result=result+dp(i,j-1,0);    for(int k=i;k<=j-1;k++)    {        if(color[k]!=color[j]) continue;        int r=dp(i,k,len[j]+ex_len)+dp(k+1,j-1,0);        result=max(result,r);    }    f[i][j][ex_len]=result;    return result;}int main(){    int n,t,cnt=1,kase=0;    scanf("%d",&t);    while(t--)    {        cnt=1;        scanf("%d",&n);        memset(f,-1,sizeof(f));        memset(len,0,sizeof(len));        memset(len,0,sizeof(len));        for(int i=1;i<=n;i++)        {            scanf("%d",&p[i]);            if(i>1&&p[i]!=p[i-1]) cnt++;            color[cnt]=p[i];            len[cnt]++;        }        printf("Case %d: %d\n",++kase,dp(1,cnt,0));    }    return 0;}


0 0