Traveling Salesman Problem

Traveling Salesman Problem

Solve:暴力解法复杂度为O(N!)这个是难以承受的,可以用朴素的DP划分思想达到O(N^2*2^N)。

N个节点有2^N个子集,记录集合中以v为结束点的集合个数为N*2^N个。

 

Best Sequence

预处理出每个字符串和其他串的最大匹配长度,跑一遍 TSP。

code:

View Code
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;

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];
vector<int>edge[MM];
int max(int x,int y) {return x>y?x:y;}
int min(int x,int y) {return x>y?y:x;}

void get_next(int m) {
    int i,j=0,k;
    fail[1]=0;
    for(i=2;i<=m;i++) {
        while(j>0 && str[j+1]!=str[i]) j=fail[j];
        if(str[j+1]==str[i]) j++;
        fail[i]=j;
    }
}

int kmp(int n,int m,int id) {
     int i,j=0,k;
     for(i=1;i<=m;i++) {
         while(j>0 && str[j+1]!=ch[id][i]) j=fail[j];
         if(str[j+1]==ch[id][i]) j++;
         if(j==n) return n;
     }
     return 0;
}

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';
//         get_next(n-i+1);
//         ans=max(kmp(n-i+1,m,s2),ans);
         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]);
//                      if(i==3&&j==1) printf("%d\n",d[1][0]);
                 }
            }
        }
    }
    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 @ 2012-11-29 23:24  zhang1107  阅读(373)  评论(0编辑  收藏  举报