poj 1390 动态规划

题意:黑书P123  有一款方块消除的游戏,游戏规则如下:n个带颜色方块排成一列,相同颜色的方块连成一个区域(如果两个相邻方块颜色相同,则这两个方块属于同一区域)。游戏时,你可以任选一个区域消去。设这个区域包含的方块数为x,则将得到x^2个分值。方块消去之后,其右边的所有方块就会向左移动,与被消去方块的左边相连。求游戏的最大得分。


分析:题目的方块可以表示成color[i], len[i], 1 <= i <= l,其中l表示有多少段不同的颜色方块。color[i]表示第i 段的颜色,len[i]表示第i 段的方块长度。

设dp[i, j, k]表示把(color[i], len[i]) , (color[i+1], len[i+1]), ……, (color[j], len[j] + k)合并的最大得分。

考虑(color[j], len[j] + k)这一段,

1.马上消掉,dp[i, j-1, 0] + (len[j] + k) ^ 2;

2.和前面的若干段一起消,可以假设这若干段中最后面得那一段是p,则此时的得分是dp[i, p, len[j]+k] + dp[p+1, j-1, 0].

于是有 dp[i, j, k] = max(f[i, j-1, 0] + (len[j] + k) ^ 2,  dp[ i, p,  len[j]+k ] + dp[p+1, j-1, 0]),其中color[p] == color[r];   

 

 

const int M = 200;
int color[205], len[205];
int dp[M][M][M];
int pos;

void readData(){
    int n; cin>>n;
    memset(len, 0, sizeof(len));
    memset(dp, 0, sizeof(dp));
    pos=0;
    while(n--){
        int a;cin>>a;
        if(a==color[pos]) len[pos]++;
        else {
            color[++pos] = a;
            len[pos]++;
        }
    }
}

int d(int i, int j, int k){
    if( dp[i][j][k] ) return dp[i][j][k];
    if(i-j==1 && k==0) return 0;
    dp[i][j][k] = d(i,j-1,0) + (len[j]+k) * (len[j]+k);
    FOR(p, i, j)
        if(color[p]==color[j]) {
            int t = d(i,p,k+len[j]) + d(p+1,j-1,0);
            checkmax(dp[i][j][k], t);
        }
    return dp[i][j][k];
}

int main(){
    int t; cin>>t;
    FOE(r, 1, t){
        readData();
        cout<<"Case "<<r<<": "<<d(1, pos, 0)<<endl;
    }
    return 0;
}

 

posted @ 2013-06-19 12:12  心向往之  阅读(711)  评论(0)    收藏  举报