Best Sequence [POJ1699] TSP-DP
http://poj.org/problem?id=1699
状态压缩,预处理出任意两个串的最长前缀和后缀的公共部分,然后DP。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//POJ1699 const int MM = 110; #define maxint 0x3f3f3f3f int N; int d[1<<11][11]; char str[MM]; int len[MM][MM]; int fail[MM]; char ch[21][MM]; int cal(int s1,int s2) { int i,j,k,n,m,ans=0; n=strlen(ch[s1]+1); m=strlen(ch[s2]+1); for(i=1;i<=n;i++) { for(j=i;j<=n;j++) str[j-i+1]=ch[s1][j]; str[n-i+2]='\0'; for(j=1;j<=(n-i+1);j++) { if(str[j]!=ch[s2][j]) break; } if(j>(n-i+1)) return n-i+1; } return 0; } void get_data() { int i,j,k; scanf("%d",&N); for(i=1;i<=N;i++) scanf("%s",ch[i]+1); memset(len,0,sizeof(len)); for(i=1;i<=N;i++) { for(j=1;j<=N;j++) { len[i][j]=cal(i,j); } } } void solve() { int i,j,k,n=(1<<N)-1,mask; memset(d,maxint,sizeof(d)); for(i=0;i<N;i++) d[1<<i][i]=len[i+1][i+1]; for(i=1;i<=n;i++) { for(j=0;j<N;j++) { if(i&(1<<j)) { mask=i&~(1<<j); for(k=0;k<N;k++) { if(mask&(1<<k)) d[i][j]=min(d[i][j],d[mask][k]+strlen(ch[j+1]+1)-len[k+1][j+1]); } } } } int ans=maxint; for(i=0;i<N;i++) ans=min(ans,d[n][i]); printf("%d\n",ans); } int main() { int ca; scanf("%d",&ca); while(ca--) get_data(),solve(); return 0; }