哈理工OJ 1847 擦除字符串(状压DP)
来源:互联网 发布:英魂之刃刷点卷软件 编辑:程序博客网 时间:2024/06/05 08:50
原题地址
擦除字符串Time Limit: 5000 MSMemory Limit: 32768 KTotal Submit: 32(17 users)Total Accepted: 16(13 users)Rating: Special Judge: NoDescription给出一个字符串s,我们每一步可以擦除当前字符串中的一个回文子串。现在问最少需要多少步才能把整个字符串擦除。例如我们能在一步里面擦除abcba从axbyczbea并且得到xyze。
Input第一行是一个整数T,代表T组测试数据,对于每组测试数据输入一个长度<=16的字符串。Output对于每组测试数据输出最少的步数。Sample Input2
aa
abbSample Output1
2
状压DP。
我们可以反过来看,将题目看成是从空串添加回文串,直至成为原串。
我们先枚举出原串中所有的回文串,虽然时间复杂度较高,但是字符串不长,所以无碍。
用一个dug数组,将回文串状态压缩成一个数,i 状态是回文串,则dug[i] = 1。比如:
原串:f g h j i u h g f
那么f g h i h g f 是一个回文串
二进制数 1 1 1 0 1 0 1 1 1 = 471
记dug[ 471 ] = 1
记增添回文串到状态i的最小次数为dp[ i ]
然后我们将每个状态进行枚举,如果这个状态 q 与前一个状态 i 比较下,是回文串的话,那么取最小值,即dp[q]=min(dp[q],dp[i]+1)。
第一次用的是记忆化搜索,严重超时!但是代码中记忆化搜索的部分没删,注释掉了。
AC代码:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;char s[17];int dp[1<<17];bool dug[1<<17];void check(int len){ for(int i=1;i<(1<<len);i++) { int flag=0; int k=len; for(int j=0;j<k;) { while(((1<<j)&i)==0) { j++; if(j>len) { break; } } while(((1<<k)&i)==0) { k--; if(k<0) { break; } } if(j<=k) { if(s[j]!=s[k]) { flag=1; break; } j++; k--; } } if(!flag) { dug[i]=1; } } return;}void dfs(int z,int ans,int len,int maxlen){ if(z==0) { if(dp[z]>ans) dp[z]=ans; return; } else { for(int i=len;i>=0;i--) { if((z&(1<<i))>0) { len=i+1; break; } } for(int i=1;i<(1<<len);i++) { if(dug[i]&&(((z^i)&(~z))==0)) { //printf("$%d\n",i); if(dp[z^i]>ans+1) { dp[z^i]=ans+1; } else { ans=dp[z^i]-1; } dfs(z^i,ans+1,len,maxlen); } } }}/*101101 z101000 i000101 z^i*//*011010 ~z100101 z000111 i100010 z^i*/int main(){ int t; scanf("%d",&t); getchar(); while(t--) { scanf("%s",s); int len =strlen(s); memset(dug,0,sizeof(dug)); memset(dp,0x3f3f3f3f,sizeof(dp)); check(len); //dfs((1<<len)-1,0,len,len);//记忆化搜索会超超超超时…… int end=1<<len; dp[0]=0; for(int i=0;i<end;i++) { int x=i^(end-1); for(int j=x;j!=0;j=(j-1)&x) { if(dug[j]==0)continue; int q=i|j; dp[q]=min(dp[q],dp[i]+1); } } printf("%d\n",dp[end-1]); } return 0;}
0 0
- 哈理工OJ 1847 擦除字符串(状压DP)
- hrbust/哈理工oj 2280 去吧,皮卡秋【状压dp】
- hrbust/哈理工oj 1809 再就业【状压dp】
- 哈理工OJ 2003 棋盘(dp问题)
- 哈理工OJ 1147 重生(水DP)
- 哈理工OJ 1597 序列问题II(水DP)
- 哈理工OJ 1179 下山(DP+深搜)
- 哈理工OJ 2002 幂集(DP问题)
- 哈理工OJ 1426 集训队的晚饭(DP)
- 哈理工OJ 2004 整数划分(经典dp问题)
- 哈理工OJ 1186 青蛙过河 (DP问题)
- 哈理工OJ 1284 编辑距离(DP问题)
- 哈理工oj/hrbust 1790 武林【DP】
- 南阳理工oj 整数划分(DP)
- 哈理工OJ 1522 子序列的和(单调队列)(dp)
- 哈理工OJ 1864 猥琐宅男——koko(dp)
- hrbust 哈理工OJ 1918 M数【数位dp基础】
- hrbust 哈理工oj 2011 一等队形【dp】
- Inverse和Cascade的比较
- Sublime3配置Python开发环境
- android截屏报getDrawingCache()==null
- NOIP模拟题 2016.11.5 [贪心] [坐标离散化] [循环序列LIS]
- 二叉树系列---判断给定的二叉树是否为二叉查找树
- 哈理工OJ 1847 擦除字符串(状压DP)
- Number
- org.hibernate.hql.ast.QuerySyntaxException is not mapped异常
- 求三角形面积
- pcl1.8.0 vs2013 win10 x64 安装配置及部分问题解决方法
- java面试必备之String类
- Andriod开发入门-第一行代码-第一个活动
- java面试必备之抽象类、接口
- java面试必备之多线程