[状压dp] hdu 4628 Pieces

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4628

Pieces

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1665    Accepted Submission(s): 862


Problem Description
You heart broke into pieces.My string broke into pieces.But you will recover one day,and my string will never go back.
Given a string s.We can erase a subsequence of it if this subsequence is palindrome in one step.  We should take as few steps as possible to erase the whole sequence.How many steps do we need?
For example, we can erase abcba from axbyczbea and get xyze in one step.
 

Input
The first line contains integer T,denote the number of the test cases. Then T lines follows,each line contains the string s (1<= length of s <= 16).
T<=10.
 

Output
For each test cases,print the answer in a line.
 

Sample Input
 
  
2 aa abb
 

Sample Output
 
  
1 2
 

Source
 

Recommend
zhuyuanchen520   |   We have carefully selected several similar problems for you:   5061  5060  5059  5058  5057 
 

Statistic | Submit | Discuss | Note
题目意思:

给一字符串,每次可以移除一个回文串,求最少要多少步,可以把该串移空。

解题思路:

状态压缩dp

dp[i]表示i状态表示的字符串是否是回文的。

对每个状态,枚举除掉是回文串的子状态进行更新。

ps:对于状态i,枚举i的子状态可以这样写  for(int j=i;j;j=(i&(j-1))

代码:

//#include<CSpreadSheet.h>

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

int dp[1<<16],ans[1<<16];
char sa[22];
int n;

int main()
{
    //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);
   int t;

   scanf("%d",&t);
   while(t--)
   {
       scanf("%s",sa);
       n=strlen(sa);

       dp[0]=false;
       for(int i=1;i<(1<<n);i++)
       {
           int l=0,r=n-1;
           bool flag=true;

           while(l<=r)
           {
               while(l<n&&(i&(1<<l))==0)
                    l++;
               while(r>=0&&(i&(1<<r))==0)
                    r--;
               if(l>r)
                    break;

               if(sa[l]!=sa[r])
               {
                   flag=false;
                   break;
               }

               l++;
               r--;
           }
           dp[i]=flag;
           //printf("i:%d %d\n",i,dp[i]);
           ans[i]=n;
       }
       ans[0]=0;
       for(int i=1;i<(1<<n);i++)
       {
           for(int j=i;j;j=(i&(j-1)))
           {
               if(dp[j])
                    ans[i]=min(ans[i],ans[i-j]+1);
           }
       }
       printf("%d\n",ans[(1<<n)-1]);



   }
    return 0;
}



猜你喜欢

转载自blog.csdn.net/cc_again/article/details/39964057