• 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;
    }
  • 相关阅读:
    Python处理海量手机号码
    javascript面向对象
    NET实现的DDD、CQRS与微服务架构
    增加打赏功能
    开发测试时给 Kafka 发消息的 UI 发送器――Mikasa
    Computational Network Toolkit (CNTK) 是微软出品的开源深度学习工具包
    线程同步和多线程优先级
    linux sed命令详解(转)
    linux sort,uniq,cut,wc命令详解 (转)
    linux awk命令详解(转)
  • 原文地址:https://www.cnblogs.com/zhang1107/p/2795501.html
Copyright © 2020-2023  润新知