http://acm.hdu.edu.cn/showproblem.php?pid=4628
题意:给个字符窜,每步都可以删除一个字符窜,问最少用多少步可以删除一个字符窜
分析:状态压缩+记忆化搜索
先打表,把每一个构成回文的字符窜的状态i都存到一个ss数组中。然后再判断某一个回文是否能
够删除,判断条件是(ans|i)==ans,ans或i等于ans,这个说明i没有多余的1
//pragma comment(linker, "/STACK:102400000,102400000") #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int MN=70000; int dp[MN]; char str[MN]; char tmp[20]; int ss[MN]; int cas; bool judge(int n)//判断回文 { for(int i=0;i<n/2;i++) { if(tmp[i]!=tmp[n-i-1]) return false; } return true; } int work(int t) { int cnt=0; while(t) { t/=2; cnt++; } return cnt; } int DFS(int ans) { if(dp[ans]!=-1) return dp[ans]; if(ans==0) return 0; int &res=dp[ans]; res=work(ans); for(int i=0;i<cas;i++) { if((ss[i]|ans)==ans) { int tmp=ans^ss[i]; res=min(res,DFS(tmp)+1); } } return res; } int main() { int i,j,tot,T; scanf("%d",&T); while(T--) { memset(dp,-1,sizeof(dp)); cas=0; scanf("%s",str); int len=strlen(str); for(i=1;i<=(1<<len)-1;i++) { int cnt=0; for(j=0;j<len;j++) { if((1<<j)&i) { tmp[cnt++]=str[j]; } } if(judge(cnt)) ss[cas++]=i; } printf("%d ",DFS((1<<len)-1)); } return 0; }