給定一張 n 個點的帶權無向圖,點從 0~n-1 標號,求起點 0 到終點 n-1 的最短hamilton路徑。 hamilton路徑的定義是從 0 到 n-1 不重不漏地經過每個點恰好一次。
輸入格式
第一行輸入整數nn。
接下來n行每行n個整數,其中第ii行第jj個整數表示點i到j的距離(記為a[i,j])。
對於任意的x,y,z,資料保證 a[x,x]=0,a[x,y]=a[y,x] 並且 a[x,y]+a[y,z]>=a[x,z]。
輸出格式
輸出乙個整數,表示最短hamilton路徑的長度。
資料範圍
1≤n≤20
0≤a[i,j]≤1e7
輸入樣例:
50 2 4 5 1
2 0 6 5 3
4 6 0 8 3
5 5 8 0 5
1 3 3 5 0
輸出樣例:
18知識點:二進位制狀態壓縮dp
思路:1.brute force
求出n個點的全排列,計算每種情況的路徑值,取最小的值。 o(n * n !) 超時。
2.二進位制狀態壓縮dp
把 n 用二進位制表示,每一位只有0和1,我們把1表示這個點已經經過,0表示這個點未被經過。
判斷語句只有1是合法的,意思是剛剛經過了這個點,此時的上乙個狀態被經過了。
建立乙個二維陣列dp[i][j]表示狀態為 i ,走到 j 點時的最短路徑。
剛開始dp[1][0]=0表示起始點0 已經經過,且最短路為0。把dp陣列初始為正無窮。
最終的目標是所有點都被經過,也就是轉態為n個1(111111…) 走到第n-1個點,所以
dp[(1<#include#include#includeusing namespace std;
const int mmax=1e6+10;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int m=1<<20,n=20;
ll dp[m][n],weight[n][n];
int main()
} dp[1][0]=0;
for(int i=0;i<(1<>j&1)}}
}} cout } 給定一張 n 個點的帶權無向圖,點從 0 n 1 標號,求起點 0 到終點 n 1 的最短hamilton路徑。hamilton路徑的定義是從 0 到 n 1 不重不漏地經過每個點恰好一次。輸入格式 第一行輸入整數n。接下來n行每行n個整數,其中第i行第j個整數表示點ii到jj的距離 記為a i,j... 哈密頓最短路徑即為從起點到終點,計算出經過圖中所有點的最短路徑。點較少的情況 由於途中點較少,可能會直接想到暴力列舉所有點的全排列,然後計算最短距離,其時間複雜度為 o n n o n n o n n 但是如果使用動態規劃,列舉每個點被經過的狀態的話,那麼可以將時間複雜度降到 o n 2 2n o ... 給定一張 n 個點的帶權無向圖,點從 0 n 1 標號,求起點 0 到終點 n 1 的最短hamilton路徑。hamilton路徑的定義是從 0 到 n 1 不重不漏地經過每個點恰好一次。輸入格式 第一行輸入整數n。接下來 n 行每行n個整數,其中第i行第j個整數表示點i到j的距離 記為a i,j...最短Hamilton路徑(二進位制 狀態壓縮dp)
Hamilton哈密頓最短路徑 二進位制狀態壓縮
最短Hamilton路徑