【hrbust700纪念】Hrbust 1847 擦除字符串【状压dp+Dfs枚举可行状态+剪枝】好题
来源:互联网 发布:mac版vmware fusion 编辑:程序博客网 时间:2024/06/18 07:50
![](http://acm.hrbust.edu.cn/Public/images/star-solid.png)
![](http://acm.hrbust.edu.cn/Public/images/star-solid.png)
![](http://acm.hrbust.edu.cn/Public/images/star-solid.png)
![](http://acm.hrbust.edu.cn/Public/images/star-solid.png)
例如我们能在一步里面擦除abcba从axbyczbea并且得到xyze。
Input第一行是一个整数T,代表T组测试数据,对于每组测试数据输入一个长度<=16的字符串。Output对于每组测试数据输出最少的步数。Sample Input2
aa
abb
Sample Output1
2
思路:
1、通过Dfs枚举所有子序列状态,并判断当前枚举出来的状态是否是一个可行状态(是否是一个回文串)因为字符串并不会很长,所以时间复杂度:O(2^len*len)的时间复杂度虽然看起来很大,其实最坏也就是2^16*16==2^20.对应枚举出来的状态i如果是回文串,我们vis【i】=1.标记此种状态为回文串。
2、接下来我们设定dp【i】表示从状态0添加回文串到状态i需要的步数。虽然我们问题上说的是让我们从一个字符串去擦除回文串需要的最少步数,而因为位运算操作之类的方便角度出发,我们其实可以将擦除回文串变成增加回文串。
3、那么dp【0】=0;ans=dp【(1<<len)-1】;其状态转移方程:dp【q】=min(dp【q】,dp【i】+1);当然,q是i在加了某个回文串之后的状态。有了状态转移方程,分析其时间复杂度,如果i,q两个状态都通过直接枚举的话,是会达到:O(1<<len*1<<len)的时间复杂度,最坏也达到了2^16*2^16==2^32显然会超时。那么我们做简单优化.
4、如果当前枚举到的i状态:首先我们将i状态按位取反得到状态tmp,然后我们判断一下这个tmp是不是一个回文串,如果是(vis【i】==1),那么状态q==tmp|i,然后tmp--。那么是不是优化到这里我们就完事大吉了呢?显然优化的还不够彻底,我们继续优化、对应状态tmp,判断过后,我们明显需要tmp--,对下一个状态进行判断,那么对应如果下一个tmp的某一位有1,而状态i也有1,显然这种情况是不需要的(重叠上了字符串,明显tmp现在非法),而且如果这个1所在位为最高位,那么将会枚举了(1<<(len-1))这些不需要枚举的情况,那么我们可以进行优化:tmp--之后,tmp&x.令其中不需要出现的1去掉、这样就能做到极大的优化。
5、思路建立的差不多过后,我们剩下的工作就是写代码啦。细节处理部分可以参考代码;
Ac代码:
#include<stdio.h>#include<string.h>#include<iostream>using namespace std;int n;int dp[1<<17];int vis[1<<17];char a[50];void Dfs(int cur,int tmp[],int sum){ if(cur==n) { char aa[17]; int cont=0; for(int i=0;i<n;i++) { if(tmp[i]==1) { aa[cont++]=a[i]; } } int flag=0; for(int i=0;i<cont/2;i++) { if(aa[i]==aa[cont-i-1])continue; else { flag=1; break; } } if(flag==0)vis[sum]=1; return ; } for(int i=0;i<2;i++) { tmp[cur]=i; Dfs(cur+1,tmp,sum+i*(1<<(n-cur-1))); }}void getmap(){ memset(vis,0,sizeof(vis)); n=strlen(a); int tmp[20]; Dfs(0,tmp,0);}int main(){ int t; scanf("%d",&t); while(t--) { scanf("%s",a); getmap(); memset(dp,0x3f3f3f3f,sizeof(dp)); int end=1<<n; 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(vis[j]==0)continue; int q=i|j; dp[q]=min(dp[q],dp[i]+1); } } printf("%d\n",dp[end-1]); }}
- 【hrbust700纪念】Hrbust 1847 擦除字符串【状压dp+Dfs枚举可行状态+剪枝】好题
- zoj 1100&& poj2411 Mondriaan's Dream (dfs&&枚举&&状态压缩dp)好题
- poj2531~剪枝dfs枚举题
- Hrbust 2160 Hunter【最短路SFPA+状压dp】好题!
- Codeforces 525E Anya and Cubes【折半枚举法+剪枝Dfs】好题~
- hrbust 1663 水果【状压dp】【原创1000篇纪念!!!】
- 哈理工OJ 1847 擦除字符串(状压DP)
- lightoj 1018 一个比较重要的状态转移的剪枝技巧....DFS+状压dp
- POJ1724ROADS(DFS+状态剪枝)
- Light OJ 1407 - Explosion 【2-sat之 3布尔变量的处理 — 枚举所有状态判断是否存在可行解 + 反向输出可行解】【好题】
- hrbust 1231/hdu 3118 Arbiter【二进制枚举】好题
- Hrbust 1256 Province Region Competition Team Play【状压dp+分段处理思想+思维】好题!好题!好题!
- hrbust 1957 干掉坏人【Dfs+暴力枚举】
- Hrbust 1361 Leyni的机器人【dp】好题
- Hrbust 2051 Mountain Subsequences【dp+思维】【哈理工OJ 800题纪念】
- [hrbust 2030] 成语接龙(状态压缩 + dfs)
- hrbust 2115,哈理工oj 2115 Equal【dfs+剪枝】
- Tempter of the Bone(DFS + 奇偶剪枝,好题)
- Redis之十五 复制
- malloc和free函数详解
- POJ 1995 Raising Modulo Numbers
- 【机房收费】-- 组合查询
- 闲来无事,看如何用DOM解析XML
- 【hrbust700纪念】Hrbust 1847 擦除字符串【状压dp+Dfs枚举可行状态+剪枝】好题
- Redis之十六 Sentinel(哨兵)
- auto和decltype的用法总结
- HDOJ-----1950Bridging signals(LIS)
- Redis之十七 集群
- 2、数据库事务
- 计算几何 The Circumference of the Circle
- HDU 1394 Minimum Inversion Number
- Mac系统安装MATLAB 2015b 破解版