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

2013 Multi-University Training Contest 3

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;
}
时间: 2024-11-16 20:51:19

[状压dp] hdu 4628 Pieces的相关文章

状压DP [HDU 3001] Travelling

Travelling Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4166    Accepted Submission(s): 1339 Problem Description After coding so many days,Mr Acmer wants to have a good rest.So travelling is

状压DP [HDU 1074] Doing Homework

Doing Homework Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5472    Accepted Submission(s): 2311 Problem Description Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lo

[AC自动机+spfa+状压dp] hdu 3247 Resource Archiver

题意: 给n个本源串,m个病毒串 求一个最多的长度的单词包含所有的本源串并不包含任意一个病毒串 串均为01串 思路: 只有10个本源串 一开始想的是直接建立完trie图 然后在图上直接spfa 结果发现 dis[60005][1030] 超内存了 这个时候就要想到 其实只有节点的mark值大于0的节点是我们需要用的 就是那些含有状压权值的节点 那么我们先记录下这些节点是哪些 然后发现其实这些不到100个节点 所以跑100遍spfa 求出两两之间的最短路 然后用这个距离 去状压dp 数组就成了 d

[AC自动机+状压dp] hdu 4534 郑厂长系列故事——新闻净化

题意:中文的题目,意思就是说有很多串,每个串都有权值,权值为999的串必须出现,-999的串必须不出现.权值在-999~999之间. 然后必须出现的串不超过8个.然后给一个全为小写目标串,问最少需要删除多少个字母才能够保证必须出现的串都出现,次数一样保证权值最大.输出次数和权值. 然后根据样例,那些必须出现的串,其实权值是0. 思路: 很明显一开始建自动机构成trie图,但是需要注意的就是mark和sum的更新.个人是把所有中间的节点的sum全部赋值成了-inf. 接着只有8个必须出现的串,所以

[AC自动机+状压dp] hdu 2825 Wireless Password

题意: 给n,m,k ,再给出m个单词 问长度为n的字符串,至少在m个单词中含有k个的组成方案有多少种. 思路: 由于m最大是10,所以可以采取状压的思想 首先建立trie图,在每个单词的结束节点标记一个mark=(1<<id),id为单词的编号 然后需要注意的,对于每个节点,应该顺着fail指针遍历一遍, 把所有的mark取一个并集. 因为就是如果单词出现包含的话,比如 she和he 我拿了she,其实等于两个都拿了. dp[i][j][k]  i步在节点j状态k的方案数 然后就是一个四重循

[状压dp] hdu 4064 Carcassonne

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4064 Carcassonne Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 857    Accepted Submission(s): 326 Problem Description Carcassonne is a tile-bas

[kmp+dp] hdu 4628 Pieces

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4622 Reincarnation Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) Total Submission(s): 2096    Accepted Submission(s): 715 Problem Description Now you are back,and

HDU 4628 Pieces(状压DP)题解

题意:n个字母,每次可以删掉一组非连续回文,问你最少删几次 思路:把所有回文找出来,然后状压DP 代码: #include<set> #include<map> #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include <iostream> #include<algorithm&

HDU 3001 Travelling 状压DP

链接:http://acm.hdu.edu.cn/showproblem.php?pid=3001 题意:还是环游地图的问题,只不过这回旅行者对自己有着严格的要求,地图上每个点的经过次数不能超过两次. 思路:依然是状压DP问题,根上一道很像,只不过这次对于每个点来说有三种状态,分别是未经过,经过一次,经过两次.所以要用三进制的数来进行状态压缩,这个关键点想明白了其他的和上一道基本一样了.对于我来说需要注意的是:能够到达某一个点经过了两次的状态的前一个状态是这个点已经经过了一次的状态,而不是从来未