Problem Description
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
abbSample Output
1
2
题意:给一个字符串,每次可以在字符串中选取任意个能组成回文串的字符(可为不连续的)去掉,单个字符亦视为回文,
思路:状压DP
字符串长度<=16,可以考虑枚举所有状态,将每个串压缩成一个状态,用0、1分别表示字符串某位置的字符去掉、保留,比较状态和子状态与相应的状态,进行状态转移取小值即可
Source Program
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<ctime>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 20
#define MOD 10007
#define E 1e-6
#define LL long long
using namespace std;
char str[N];
int sta[N];
int dp[1<<N];
int len;
int init(int x){
int head=0;
memset(sta,0,sizeof(sta));
for(int i=0;i<=len;i++)
if(x&(1<<i))
sta[head++]=i;
head--;
for(int i=0;i<head/2;i++)//从中点向两端看,判断是否是回文
if(str[sta[i]]!=str[sta[head-i]])//若不是回文,则返回是回文的状态x的长度
return head;
return 1;
}
int main()
{
int n;
scanf("%d",&n);
while(n--){
memset(dp,0,sizeof(dp));
scanf("%s",str);
len=strlen(str);
int allState=1<<len;
for(int i=1;i<allState;i++){//枚举所有状态
dp[i]=init(i);//对每一状态初始化
for(int j=i;j>0;j=(j-1)&i)
dp[i]=min(dp[i],dp[j]+dp[j^i]);
}
printf("%d\n",dp[allState-1]);
}
return 0;
}

本文介绍了一种使用状态压缩动态规划(状压DP)解决特定字符串操作问题的方法。在一个长度不超过16的字符串中,目标是在最少的步骤内通过去除可形成回文的子序列来清空整个序列。文章详细解释了如何利用状态压缩和动态规划减少计算复杂度,并给出了完整的源代码示例。
&spm=1001.2101.3001.5002&articleId=82936564&d=1&t=3&u=c9135ce4e68f44aeaffd4a37d05f3963)
247

被折叠的 条评论
为什么被折叠?



