这是一个大水题啊。。。
因为比赛时不会算复杂度耽误半天。
i从0到2^n枚举集合i的所有分割两半的情况的复杂度为O(3^n),可以想象这个过程相当于是给每个位标记0,1,2(0表示不选,1,2表示两个集合)
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; char s[20]; int vis[1<<16]; int main(){ int t,T,i,j,len; scanf("%d",&T); for(t=1;t<=T;t++){ scanf("%s",s); len=strlen(s); for(i=1;i<(1<<len);i++){ bool flag=1; int l=0,r=len-1; while(l<r){ while(l<len && ((i&(1<<l))==0)) l++; while(r>=0 && ((i&(1<<r))==0)) r--; if(s[l]!=s[r]){ flag=0; break; } l++,r--; } if(flag) vis[i]=1; else vis[i]=len; } for(i=1;i<(1<<len);i++){ if(vis[i]==1)continue; for(j=(i-1)&i;j;j=(j-1)&i) vis[i]=min(vis[i],vis[i-j]+vis[j]); } printf("%d ",vis[(1<<len)-1]); } }