1. 程式人生 > >郵箱:[email protected]

郵箱:[email protected]

TSP

TSP問題非常經典,(旅行商問題)是指旅行家要旅行n個城市,要求各個城市經歷且僅經歷一次然後回到出發城市,並要求所走的路程最短。
這裡寫圖片描述
如圖,從0開始,把1,2,3都走一遍然後回到0,求最短路徑。

方法有很多

  1. 暴力法:城市順序全排列,找到最短距離,可以給伺服器跑個兩天沒問題
  2. 回溯法:走一遍,不行回來換條路,幾個小時吧
  3. 分支定界法:空間消耗比較大
  4. 動態規劃法:空間複雜度要求太高了,城市稍微比較多的樣例程式就會崩
  5. 模擬退火演算法,遺傳演算法,蟻群演算法:比較高階了
  6. 禁忌搜尋:會了無壓力

回溯法

對於路比較少的題還是可以做一做的

(鏈式前向星存20條邊未免有點大材小用了,還不如矩陣存來的有用)

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<list>
#include<vector>
#include<stack>
#include<queue>
#include<ctime>
#include<cstdlib>
//#include<windows.h> #include<functional> #define D long long #define F double #define MAX 0x7fffffff #define MIN -0x7fffffff #define mmm(a,b) memset(a,b,sizeof(a)) #define pb push_back #define mk make_pair #define fi first #define se second #define pill pair<int, int> #define
for1(i,a,b) for(int i=a;i<=b;i++)
#define for2(i,a,b) for(int i=a;i>=b;i--) #define ini(n) scanf("%d",&n) #define inll(n) scanf("%lld",&n) #define outisp(n) printf("%d ",n) #define outllsp(n) printf("%lld ",n) #define outiel(n) printf("%d\n",n) #define outllel(n) printf("%lld\n",n) using namespace std; #define N 500100 #define MOD ((int)1e9+7) #define random(a,b) (rand()%(b-a+1)+a) #define stop Sleep(2000) #define CLS system("cls") const string el="\n"; const string elel="\n\n"; const string sp=" "; const string spsp=" "; const string tab="\t"; int head[30]; int now; struct node{ int to,nex,val; }e[2000]; int n,m; int ans=1000000; int vis[30]; int nuvis; void add(int a,int b,int v){ e[++now].to=b;e[now].val=v;e[now].nex=head[a];head[a]=now; e[++now].to=a;e[now].val=v;e[now].nex=head[b];head[b]=now; } void dfs(int be,int v){ nuvis++;vis[be]=1; if(nuvis==n){//訪問完 for(int i=head[be];~i;i=e[i].nex){ if(e[i].to==1){ ans=min(ans,v+e[i].val);//因為可能去1的路有很多條所以不能結束還有繼續判斷return ; } } } for(int i=head[be];~i;i=e[i].nex){ if(vis[e[i].to])continue; if(v+e[i].val>=ans)continue; dfs(e[i].to,v+e[i].val); nuvis--;vis[e[i].to]=0; } } int main(){ mmm(head,-1);now=0;mmm(vis,0);nuvis=0; ini(n),ini(m); for1(i,1,m){ int a,b,v;ini(a),ini(b),ini(v); add(a,b,v); } dfs(1,0); if(n!=1) cout<<ans<<el;//磨人的小妖精(卡人的資料。。) else cout<<0<<el; } /* 4 6 1 2 30 1 3 6 1 4 4 2 3 5 2 4 10 3 4 20 */ /* 3 4 1 2 1 1 2 2 2 3 3 3 1 5 */ /* 4 12 1 2 3 2 1 5 1 4 3 4 1 7 1 3 6 3 1 6 2 3 2 3 2 4 2 4 3 4 2 7 3 4 5 4 3 2 */