HDU6212 区间dp 好题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/du_lun/article/details/82688782

传送门

思路:要是对原串区间dp感觉无从下手,需要重要的一步就是转化,转化成连续的01数量串,比如10010=1211

这样的话每隔一个就是同一类的。

对于单个数字,需要的就是3-a[i],

对于一个区间,可以由三类转移

1. 把区间分成 两份  例如 11 00   ans=2

2.中间消去两头相遇消去  例如11 00 1  ans=1

3.三块相遇消去   例如 1 00 1 00 11   ans=2

第三种情况这三块要满足中间必须是1,两边加起来和<=3, 因为这样消去 第一个00的时候,才不会出现将1消去的情况,

然后消去第二个00,三块相遇消去

#include<bits/stdc++.h>
using namespace std;

int dp[210][210], a[210];
char s[210];

int main(){
    int T, cas=0;
    scanf("%d", &T);
    while(T--){
        scanf("%s", s);
        int len=strlen(s);
        int m=1; a[m]=1;
        for(int i=1; i<len; i++){
            if(s[i]==s[i-1]) a[m]++;
            else a[++m]=1;
        }
        memset(dp, 0x3f, sizeof dp);

        for(int i=1; i<=m; i++)dp[i][i]=3-a[i], dp[i][i-1]=0;

        for(int t=1; t<m; t++){
            for(int i=1; i+t<=m; i++){
                int j=i+t;
                for(int k=i; k<j; k++){
                    dp[i][j]=min(dp[i][j], dp[i][k]+dp[k+1][j]);
                    if(t>=4 && a[k]==1 && ((k-i+1)&1) && ((j-k+1)&1) && a[i]+a[j]<=3)
                        dp[i][j]=min(dp[i][j], dp[i+1][k-1]+dp[k+1][j-1]);
                }
                if((t+1)&1)
                    dp[i][j]=min(dp[i][j], dp[i+1][j-1]+(a[i]+a[j]==2));
            }
        }

        printf("Case #%d: %d\n", ++cas, dp[1][m]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/du_lun/article/details/82688782