HDOJ 4628 - Pieces 状态压缩DP..枚举所有子集进行更新

来源:互联网 发布:oanda 数据接口 编辑:程序博客网 时间:2024/06/08 07:54

    开始题目看错了....以为是连着的回文才能一次消掉..题目的意思是分开的也行...

    串最长16..很容易想到状态压缩DP....当本状态回文时..直接为1...否则是其两个相对其互补的子集并的最小值...更新的时候要枚举其所有的子集...

    比如说二进制状态t..要枚举其所有的子集..for(int i=t;i;i=(i-1)&t) 


Program:

#include<iostream>#include<stdio.h>#include<string.h>#include<cmath>#include<queue>#include<stack>#include<set>#include<algorithm>#define ll long long#define oo 1000000007#define pi acos(-1.0)#define MAXN 16using namespace std;    char s[MAXN];int dp[1<<MAXN],n;bool IsPalindrome(int x){       char ss[MAXN];       int i,j,m;       m=0;       for (i=0;i<n;i++)          if (x & (1<<i))             ss[m++]=s[i];       i=0,j=m-1;       while (i<=j && ss[i]==ss[j]) i++,j--;       if (i>j) return true;       return false;}int main(){        int T;        scanf("%d",&T);       while (T--)       {                scanf("%s",s);                n=strlen(s);                dp[0]=0;                for (int t=1;t<(1<<n);t++)                {                       dp[t]=oo;                       if (IsPalindrome(t)) dp[t]=1;                        for(int i=t;i;i=(i-1)&t)  //枚举t的所有子集                          dp[t]=min(dp[t],dp[i]+dp[t^i]);                    }                printf("%d\n",dp[(1<<n)-1]);       }       return 0;}