[状压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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值