zoukankan      html  css  js  c++  java
  • 【bzoj2121】字符串游戏 【动态规划dp】

    题目链接
    感觉这个dp还是蛮棒棒的^^
    我们让f[i][j][a][b]=0/1表示大串中i~j的子串与第a个小串1~b的字串是否完全相同,ok[i][j]=0/1表示大串中i~j的子串能否全部拿空,dp[i]表示大串前i个字符最少剩下几个。
    则有状态转移方程
    f[i][j][a][b]|=(f[i][j1][a][b1] and t[j]==s[a][b])||(f[i][k][a][b] and ok[k+1][j])(k=i..j1)
    ok[i][j]|=f[i][j][a][len[a]]
    dp[i]=min(dp[i1]+1,dp[j] and ok[j+1][i])
    观察发现通过状压可以压掉一维的空间复杂度和时间复杂度。于是就可以乱搞了。

    非状压代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int lt,n,ls[35],ok[151][151],f[151][151][31][21],dp[151];
    char t[155],s[35][25];
    int main(){
        scanf("%s",t+1);
        lt=strlen(t+1);
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",s[i]+1);
            ls[i]=strlen(s[i]+1);
        }
        for(int i=1;i<=lt;i++){
            for(int j=1;j<=n;j++){
                if(t[i]==s[j][1]){
                    f[i][i][j][1]=1;
                    ok[i][i]|=f[i][i][j][ls[j]];
                }
            }
        }
        for(int i=lt;i>=1;i--){
            for(int j=i+1;j<=lt;j++){
                for(int a=1;a<=n;a++){
                    for(int b=1;b<=ls[a];b++){
                        f[i][j][a][b]|=(f[i][j-1][a][b-1]&&t[j]==s[a][b]);
                        for(int k=i;k<=j-1;k++){
                            f[i][j][a][b]|=(f[i][k][a][b]&&ok[k+1][j]);
                        }
                    }
                    ok[i][j]|=f[i][j][a][ls[a]];
                }
            }
        }
        for(int i=1;i<=lt;i++){
            dp[i]=dp[i-1]+1;
            for(int j=0;j<i;j++){
                if(ok[j+1][i]){
                    dp[i]=min(dp[i],dp[j]);
                }
            }
        }
        printf("%d
    ",dp[lt]);
        return 0;
    }

    状压代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int lt,n,bin[35],ls[35],ok[151][151],f[151][151][31],dp[151];
    char t[155],s[35][25];
    int main(){
        scanf("%s",t+1);
        lt=strlen(t+1);
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",s[i]+1);
            ls[i]=strlen(s[i]+1);
        }
        bin[0]=1;
        for(int i=1;i<=30;i++){
            bin[i]=bin[i-1]<<1;
        }
        for(int i=1;i<=lt;i++){
            for(int j=1;j<=n;j++){
                if(t[i]==s[j][1]){
                    f[i][i][j]|=bin[1];
                    ok[i][i]|=(f[i][i][j]&bin[ls[j]]);
                }
            }
        }
        for(int i=lt;i>=1;i--){
            for(int j=i+1;j<=lt;j++){
                for(int a=1;a<=n;a++){
                    for(int b=1;b<=ls[a];b++){
                        f[i][j][a]|=((f[i][j-1][a]&bin[b-1])&&t[j]==s[a][b])*bin[b];
                    }
                    for(int k=i;k<=j-1;k++){
                        if(ok[k+1][j]){
                            f[i][j][a]|=f[i][k][a];
                        }
                    }
                    ok[i][j]|=(f[i][j][a]&bin[ls[a]]);
                }
            }
        }
        for(int i=1;i<=lt;i++){
            dp[i]=dp[i-1]+1;
            for(int j=0;j<i;j++){
                if(ok[j+1][i]){
                    dp[i]=min(dp[i],dp[j]);
                }
            }
        }
        printf("%d
    ",dp[lt]);
        return 0;
    }
  • 相关阅读:
    uva 147 Dollars
    hdu 2069 Coin Change(完全背包)
    hdu 1708 Fibonacci String
    hdu 1568 Fibonacci
    hdu 1316 How Many Fibs?
    poj 1958 Strange Towers of Hanoi
    poj 3601Tower of Hanoi
    poj 3572 Hanoi Tower
    poj 1920 Towers of Hanoi
    筛选法——素数打表
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476867.html
Copyright © 2011-2022 走看看