hdu4628枚舉子集狀壓dp

題目大意:
給一個字符串,每次可以刪除一個可不連續迴文子串,問最少刪幾次可以全部刪完。

思路:
因爲字符串長度最大16,所以可用二進制狀態表示, 1表示選取這個字符,0不選,組成一個子串。
先預處理出所有狀態,看這個狀態是不是迴文。
f[i]表示狀態i最少幾次可以全刪完, 初始化f數組INF
f[i] = min{f[i], f[s]+1 } s是i的子集。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;

typedef long long int64;
const int INF = 0x3f3f3f3f;
const int MAXN = (1<<16)+10;

char str[20];
bool check[MAXN];
int f[MAXN];
int maxSta;

bool isPalind(int st, int len){
    char sub[20];
    int idx = 0;
    for(int i=0; i<len; ++i){
        if( (st>>i)&1 )  
            sub[idx++] = str[i];
    }
    for(int i=0; i<idx/2; ++i){
        if(sub[i] != sub[idx-1-i]) 
            return false;
    }
    return true;
}

int main(){

    int T;
    scanf("%d", &T);
    check[0] = false;
    while(T--){

        scanf("%s", str);
        int len = strlen(str);
        maxSta = (1<<len)-1;
        for(int i=1; i<=maxSta; ++i){
            check[i] = isPalind(i, len);                       
        }

        memset(f, 0x7f, sizeof(f));
        f[0] = 0;
        for(int i=1; i<=maxSta; ++i){
            for(int s=i; s; s=(s-1)&i)
                if(check[s])
                    f[i] = min(f[i], f[i^s]+1);
        }
        printf("%d\n", f[maxSta]);

    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章