您的位置:首页 > 其它

HDU 4628 Pieces(状态压缩DP)

2015-08-31 19:35 405 查看
题目链接:传送门 

题意:

给定一个长度小于16的字符串然后每次可以去掉它的一个回文子序列,问最少删除多少次可以使这个字符串为空。

分析:

首先预处理出这个字符串的所有回文子序列,然后将其压缩成二进制x,然后dp[x]表示这个序列删除所需要的最小的步数,然后dp[x] = min(dp[x],dp[sub])sub表示x的所有子序列。

代码如下:

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;

const int maxn = 1<<17;

const int inf = 0x3f3f3f;

int dp[maxn];

int check(string s){
int n = s.length();
for(int i=0,j=n-1;i<j;i++,j--)
if(s[i]!=s[j])
return 0;
return 1;
}

void init(string str){
int len = str.length();
for(int i=1;i<(1<<len);i++){
string tmp;
int cnt = 0;
for(int j=0;j<len;j++){
if((1<<j)&i)
tmp=tmp+str[j],cnt++;
}
if(check(tmp)){
dp[i]=1;
}
}
}

int main()
{
int t;
scanf("%d",&t);
while(t--){
string str;
cin>>str;
memset(dp,inf,sizeof(dp));
init(str);
dp[0]=0;
int len = str.length();
for(int i=1;i<(1<<len);i++){
for(int j=i;j>0;j=i&(j-1)){//枚举所有的子状态。
dp[i]=min(dp[i],dp[i-j]+dp[j]);
}
}
printf("%d\n",dp[(1<<len)-1]);
}
return 0;
}
/****
123
aaaaaaaaaa
aaabb
***/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: