hdu6212 Zuma(区间dp)

题意:

给定串S,只由0和1组成,
现在你在玩祖玛游戏,你可以选择一个位置,插入一个0或者一个1,
当连续的0或连续的1大于等于3的时候,可以将他们消除,
同时将剩余部分拼接,如果拼接之后又出现大于等于3的相同数,继续消除。
问最少插入多少个数字可以将所有数都消除。

数据范围:|S|<=200,保证一开始不存在大于等于3个的连续相同数字

解法:
区间dp,
先合并相同的数,最后会分成若干段,
假设第i段的长度为a[i],
令d[i][j]表示消除[i,j]的最小代价,
合并有三种方式:
1.直接由两个子区间合并,d[i][k]+d[k+1][j]
2.当i和j数字相同的时候,可以先将中间消除,然后合并a[i]和a[j],
d[i+1][j-1]+(a[i]+a[j]<3)
3.i和j的中间存在一个k,满足i,k,j数字相同,
且a[i]+a[k]<3,a[k]+a[j]<3,
此时可以将a[i+1][k-1]和a[k+1][j-1]消除,
然后i,k,j三者合并消除
code:
#include<bits/stdc++.h>
using namespace std;
const int maxm=205;
int d[maxm][maxm];
int a[maxm];
char s[maxm];
int n;
signed main(){
    int T;cin>>T;
    signed cas=1;
    while(T--){
        scanf("%s",s+1);
        n=strlen(s+1);
        //合并连续的
        int m=0;
        for(int i=1;i<=n;i++){
            if(s[i]==s[i-1])a[m]++;
            else a[++m]=1;
        }
        //init
        for(int i=1;i<=m;i++){
            for(int j=i;j<=m;j++){
                d[i][j]=1e9;
            }
        }
        for(int i=1;i<=m;i++){
            d[i][i]=3-a[i];
        }
        //dp
        for(int len=2;len<=m;len++){
            for(int i=1;i<=m;i++){
                int j=i+len-1;
                if(j>m)break;
                for(int k=i;k<j;k++){//由两个子区间合并得来
                    d[i][j]=min(d[i][j],d[i][k]+d[k+1][j]);
                }
                if(len%2){//a[i]和a[j]的数一样,先消除中间
                    if(a[i]+a[j]==2){
                        d[i][j]=min(d[i][j],d[i+1][j-1]+1);
                    }else{
                        d[i][j]=min(d[i][j],d[i+1][j-1]);
                    }
                    if(a[i]+a[j]<4){//找i,k,j消除
                        for(int k=i+2;k<j;k+=2){
                            if(a[k]==1){
                                d[i][j]=min(d[i][j],d[i+1][k-1]+d[k+1][j-1]);
                            }
                        }
                    }
                }
            }
        }
        //output
        printf("Case #%d: ",cas++);
        cout<<d[1][m]<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值