好伤心啊,竟然想出来是状态压缩但写不出来,看来还是题目写得太少了。
大致题意:给定一个串,每次可以删除一个回文子串,问把全串删干净的最少次数。
本人反正想了半天也就只有状态压缩能够存储其状态了,状态转移方程 dp[x] = min(dp[x],dp[k]+dp[y] ),(x和y是x的2个子集,且其并集为x),
初始化dp[x]时,如果其为回文串,必须初始化为1,因为dp[x]是这个状态下需要最少的次数,最后的结果便是dp[(1<<len)-1] (提醒一句,刚学状态压缩的小伙伴得注意位运算的优先级了,比较低啊)。
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char str[20];
int dp[1<<16],len,tot;
int deal(int x)//用来判断其是否为回文串,是的话就返回1,不然就返回其字符数
{
int nw[20],i=0,e=1;
while(x>0)
{
if(x&1)
{
nw[++i] = e;
}
x>>=1;
++e;
}
e = i/2;
for(int j=1;j<=e;++j)
if(str[nw[j]]!=str[nw[i+1-j]])
return i;
return 1;
}
int main(void)
{
int t;
cin>>t;
getchar();
while(t--)
{
gets(str+1);
len = strlen(str+1);
tot = (1<<len)-1;
for(int i=1;i<=tot;++i)
{
dp[i] = deal(i);
for(int j=i;j;j=(j-1)&i)//j为i的一个子集
{
int k = j^i;//k为i的另外一个子集
dp[i] = min(dp[i],dp[j]+dp[k]);
}
}
cout<<dp[tot]<<endl;
}
return 0;
}