题目链接:传送门
题意:
给定一个长度小于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 ***/
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-26 06:30:39