您的位置:首页 > 其它

Pieces (状态dp)

2017-12-10 21:16 134 查看
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.

InputThe 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.OutputFor each test cases,print the answer in a line.Sample Input
2
aa
abb

Sample Output
1
2


题目大概:

给出一个字符串,每次可以删除一个回文串,回文串的每个字符可以不连续的存在于字符串内,问最少需要多少步,才能全部删除所有的字符串。

思路:

状态dp

需要预处理出所有的回文串状态。

dp【i】到了i状态时,用了的步数。

状态转移方程dp[j-st[k]]=min(dp[j]+1,dp[j-st[k]]);

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int ma=18;
int st[1<<ma],dp[1<<ma];
int n;
char s[ma];
int pan(int x)//判断该状态是否是回文串
{
char ss[ma];
int i=0;
int ans=n;
while(x>0)//找出回文串
{
if(x&1)
ss[i++]=s[ans];
ans--;
x>>=1;
}
ss[i]='\0';
int l=strlen(ss);
int j=l-1;
for(i=0;i<l;i++)//判断是否是回文串
{
if(ss[i]!=ss[j--])return 0;
}
return 1;
}

int sove()//找出该序列的所有回文串状态
{
int t=1<<n;
int j=0;
for(int i=0;i<t;i++)//枚举所有状态
{
if(pan(i))st[j++]=i;//保存状态
}
return j;
}
int main()
{
int t;
cin>>t;
getchar();
while(t--)
{
gets(s+1);
n=strlen(s+1);
memset(dp,0x3f,sizeof(dp));
dp[(1<<n)-1]=0;
int t1=sove();
int t2=1<<n;
for(int j=t2-1;j>=0;j--)//枚举所有的状态
{
for(int k=0;k<t1;k++)//枚举回文串状态
{
if(((st[k]&j)==st[k])&&dp[j]!=-1)//回文串状态包含于该状态
dp[j-st[k]]=min(dp[j]+1,dp[j-st[k]]);//去掉回文串后的状态所需步骤
}
}
printf("%d\n",dp[0]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息