Blocks UVA - 10559

这道题要想dp,主要是难在状态表示吧。

首先,光记录1...i合并不对,这样处理不了12321的问题,所以,要记录l...r合并。

怎么让两段分开的颜色合并呢?

比如1213,如何合并两个1?

把这个颜色保存进状态呗。熟悉dp的人都知道,这时候只要关注一个颜色就好

然后我这样表示状态[l][r][c],将l...r合并后剩下c个r的颜色

但这样表示不好,因为你肯定是将两段颜色合并起来,你把一种颜色的数量叠加上去就好了,不用表示具体还剩几个

这样表示状态:[l][r][c],右边加上c个r的颜色,再将l...r合并

然后状态转移就不难了

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

const int N=200+2;

int dp[N][N][N];

int cnt[N],a[N];

int dps(int l,int r,int c)
{
    int&ret=dp[l][r][c];
    if(ret>=0)
        return ret;
    if(l==r)
        return ret=(c+cnt[l])*(c+cnt[l]);
    ret=0;
    for(int k=l;k<r;k++)
    {
        ret=max(ret,dps(l,k,0)+dps(k+1,r,c));
        if(a[r]==a[k])
            ret=max(ret,dps(l,k,c+cnt[r])+dps(k+1,r-1,0));
    }
    return ret;
}


int main()
{
    int T;
    cin>>T;
    for(int t=1;t<=T;t++)
    {
        int n,cur=0,v;
        cin>>n;
        a[0]=-1;
        for(int i=1;i<=n;i++)
        {
            cin>>v;
            if(v==a[cur])
                cnt[cur]++;
            else 
                a[++cur]=v,
                cnt[cur]=1;
        }
        memset(dp,0xff,sizeof dp);
        printf("Case %d: %d\n",t,dps(1,cur,0));
    }
    return 0;
}

 

posted @ 2018-06-30 11:31  mgnfcnt  阅读(104)  评论(0)    收藏  举报