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
Sample Output
题目大概:
给出一个字符串,每次可以删除一个回文串,回文串的每个字符可以不连续的存在于字符串内,问最少需要多少步,才能全部删除所有的字符串。
思路:
状态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;
}
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;
}
相关文章推荐
- [hdu4628 Pieces]二进制子状态,DP
- HDU 4628 Pieces(状态压缩dp)
- HDU 4628 Pieces(DP + 状态压缩)
- hdu 4628 Pieces (状态压缩dp)
- hdu 4614 pieces 状态DP
- N - Pieces (状态dp)
- hdu 4628 Pieces (状态压缩+二进制枚举+dp)
- hdu 4628 Pieces 状态压缩DP
- HDU 4628 Pieces(状态压缩DP)
- hdu 4628 Pieces(状态压缩+DP,4级)
- hdu 4628 Pieces 状态压缩DP
- 2013多校第三场 --Pieces--状态压缩DP
- hdu 4628 Pieces (状态压缩dp)
- HDOJ 4628 - Pieces 状态压缩DP..枚举所有子集进行更新
- hdu 4628 Pieces(状态压缩DP)
- hdu - 4628 - Pieces(状态压缩dp)
- hdu 3001 Travelling//状态压缩DP
- 区间dp状态的考虑与临界的分析
- 状态压缩DP 小结
- HDU 1074 Doing Homework(状态压缩DP)