【旅行商問題TSP】【狀態壓縮dp】【記憶化dp】
阿新 • • 發佈:2018-12-13
【題意】
給定一個n個頂點組成的帶權的有向圖的距離矩陣d[i,j],要求從0開始結果所有點一次回到0,問所經過邊的總權重的最小值為多少
【思路】
旅行商問題TSP,狀態壓縮dp,記憶化dp
【分析】
假設當前已經訪問過的頂點集合為S,(起點0當作還未訪問過的點),當前所在的頂點為v,用dp[S][v]表示從v出發訪問剩餘所有的點最終回到0的最小權重和。
dp[V][0]=0;
dp[S][u]=min(dp[S|{v}[v]]+a[u][v]) ( v不屬於S )
【程式碼】
#include<bits/stdc++.h> using namespace std; const int maxn = 11; const int inf = 0x3f3f3f3f; int a[maxn][maxn]; int dp[1 << maxn][maxn];//dp[i][j]表示已經經過的節點集合為i,當前位於j,從j出發訪問剩餘節點回到0的最小距離 int n; int dfs(int S, int u) { if (dp[S][u] != -1)return dp[S][u]; if (S == (1 << (n+1)) - 1 && u == 0) return dp[S][u] = 0; int res = inf; for (int v = 0; v <= n; v++) { if (!(S >>v & 1)) { res = min(res, dfs(S | (1 << v), v)+a[u][v]); } } return dp[S][u] = res; } int main() { while (~scanf("%d", &n),n) { for (int i = 0; i <= n; i++) { for (int j = 0; j <= n; j++) { scanf("%d", &a[i][j]); } } for (int k = 0; k <= n; k++) { for (int i = 0; i <= n; i++) { for (int j = 0; j <= n; j++) { a[i][j] = min(a[i][j], a[i][k] + a[k][j]); } } } memset(dp, -1, sizeof(dp)); printf("%d\n", dfs(0, 0)); } }