HDU 4628 Pieces

Pieces

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

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
 

题意:

        给定一个串,每次可以删除一个回文子串,问把全串删干净的最少次数。

        这里的字串任意选,不要求连续。

思路: 看到S<=16可能条件反应可以状态压缩了,仔细一看还真是,对于每个状态可以枚举子集串,枚举子串是老生常谈的

       算法了,这里详细写一下。比如 abcd 有4个数码,对于每个数码可以选也可以不选,一共2^4种,“” ,a ,b ,c ,d',ab ....abcd

       当然了,空子串排除,那么总共的字串是2^串长-1 ,将串“映射”成数字,比如a-->1000 ,b--->0100 ,c-->0010 ,ad--1001 ,

       adcd-->1111 ,这样做即可把所有的子串枚举出来。但是此题要求字串为回文,这只需要稍加判断即可,啰嗦一句,其实STL

       熟悉了是比较方便编码的,不要太过于排斥STL 。

           DP的部分就是个类似背包了 。注意代码里的一点  j&=i ,j表示字串 ,I 表示母串 ,如果注释j&=i ,会TL 。

      举个例子吧。比如i=100000 , 事实上字串只有100000 。只需要枚举100000即可, 如10100 ,只需枚举10100 ,10000 ,00100

      即可,j=j&i 起到加速作用(不要太过于纠结这里,可能上厕所的时候就恍然大悟了), 可以用笔画一下。

 
#include <iostream>
#include <string.h>
#include <string>
#include <algorithm>
#include <stdio.h>
#include <queue>
#include <set>
#include <limits.h>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std ;
struct Me{
   string str ;
   int is_palindrome[(1<<16)+10] ;
   int dp[(1<<16)+10] ;
   Me(){}
   Me(string s):str(s){}
   void get_is_palindrom(){
      memset(is_palindrome,0,sizeof(is_palindrome)) ;
      for(int i=1;i<(1<<str.length());i++){
         vector<int>vec ;
         vec.clear() ;
         for(int j=0;j<str.length();j++){
            if(i&(1<<j))
                vec.push_back(j) ;
         }
         int k ;
         for(k=0;k<vec.size();k++){
            if(str.at(vec[k])!=str.at(vec[vec.size()-k-1]))
                 break ;
         }
         if(k==vec.size())
            is_palindrome[i]=1 ;
      }
   }
   void DP(){
       get_is_palindrom() ;
       fill(dp,dp+(1<<str.length()),16) ;
       dp[0]=0 ;
       for(int i=1;i<(1<<str.length());i++){
          for(int j=i;j>=1;j--){
              if(is_palindrome[j])
                  dp[i]=Min(dp[i],dp[i-j]+1) ;
              j&=i ;   //这个注意
} } } int gao_qi(){ DP() ; return dp[(1<<str.length())-1] ; } }; int main(){ int T ; string s ; cin>>T ; while(T--){ cin>>s ; Me me(s) ; cout<<me.gao_qi()<<endl ; } return 0 ; }
 
原文地址:https://www.cnblogs.com/liyangtianmen/p/3227246.html