题目:http://acm.hdu.edu.cn/showproblem.php?pid=4628
先初始化判断每个集合是不是回文串,然后倒推 dp[s]=min(dp[s],dp[s-s0]+1),(其中s0表示s的子集)
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int c[1<<16],dp[1<<16],map[20];
int main(){
char s[20];
int t,i,n,cnt;
scanf("%d",&t);
while(t--){
scanf("%s",s);
n=strlen(s);
memset(c,0,sizeof(c));
for(int i=0;i<(1<<n);i++){
cnt=0;
for(int j=0;j<n;j++){
if((1<<j)&i) map[cnt++]=s[j];
}
int ok=1;
for(int l=0,r=cnt-1;l<r;l++,r--){
if(map[l]!=map[r]){
ok=0;
break;
}
}
c[i]=ok;
}
dp[0]=0;
int all=(1<<n)-1;
for(int i=1;i<(1<<n);i++){
dp[i]=999999999;
for(int j=i;j;j=(j-1)&i)
if(c[j]==1) dp[i]=min(dp[i],dp[i-j]+1);
}
printf("%d\n",dp[all]);
}
return 0;
}