100道动态规划——34 UVA 10559 Blocks 状态的定义 状态转移方程

        好吧,我想到的是枚举决策。。。

        居然是个类似于区间DP的感觉。恩。。确实是呀,只不过是需要在DP的时候附加上额外的条件

       定义状态dp[i][j][k]表示区间i~j且右边附加了k个与j同色的方块的最大值

       每次考虑把最右边的消去,既然是考虑把最右边的消去的话,那么就有两种消去方法,第一种是直接这一次消去,第二种是留着以后消去。

       关于第二种消去的办法是枚举i~j中除去j以外的每段与j同色的色块的右端,考虑把当前的最右边的色块附在这一段的最右边,语言感觉有点没有表述的清楚,

       状态转移方程是dp[i][j][k]=dp[i][ri][0]+(j-ri+k)*(j-ri+k),其中ri是把右端消去后的新起始点,也就是右边第一个不与j同色方块的位置

        第二种转移则是枚举每一段与j同色的右端,假设为le,方程是dp[i][j][k]=max(dp[i][j][k],dfs(dp[i][le][k+j-ri])+dfs(dp[le+1][ri][0]))相当于两段之和

        挺好的题目

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxm=210;

int times,n,kcase,color[maxm],dp[maxm][maxm][maxm],dfs(int i=1,int j=n,int k=0);
void init();

int main(){
    ios_base::sync_with_stdio(false);
    cin>>times;
    while(times--){
        cin>>n;
        init();
        for(int i=1;i<=n;++i)
            cin>>color[i];
        cout<<"Case "<<++kcase<<": "<<dfs()<<endl;
    }
    return 0;
}

void init(){
    memset(dp,0,sizeof dp);
}

int dfs(int i, int j, int k){
    if(i>j)
        return 0;
    if(dp[i][j][k])
        return dp[i][j][k];
    int ri=j;
    while(ri>=i&&color[j]==color[ri])--ri;
    dp[i][j][k]=dfs(i,ri,0)+(j-ri+k)*(j-ri+k);
    for(int le=i;le<=ri;++le)
    if(color[le+1]!=color[le]&&color[le]==color[j])
    dp[i][j][k]=max(dfs(i,le,j-ri+k)+dfs(le+1,ri,0),dp[i][j][k]);
    return dp[i][j][k];
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值