Best Sequence [POJ1699] TSP-DP

http://poj.org/problem?id=1699

状态压缩,预处理出任意两个串的最长前缀和后缀的公共部分,然后DP。

View Code
//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;
}

 

posted @ 2013-04-17 13:42  zhang1107  阅读(263)  评论(0编辑  收藏  举报