0
点赞
收藏
分享

微信扫一扫

Pieces (状态dp)


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.


Input The 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.

Output For 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;
}






举报

相关推荐

0 条评论