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 
#include 
#include 

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<<": "<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];
}


你可能感兴趣的:(区间DP,我说过的,CCPC拿到铜了,就做100道动态规划,100道动态规划)