最短Hamilton路徑(二進位制 狀態壓縮dp)

2021-10-02 17:09:56 字數 1237 閱讀 7762

給定一張 n 個點的帶權無向圖,點從 0~n-1 標號,求起點 0 到終點 n-1 的最短hamilton路徑。 hamilton路徑的定義是從 0 到 n-1 不重不漏地經過每個點恰好一次。

輸入格式

第一行輸入整數n。

接下來n行每行n個整數,其中第i行第j個整數表示點ii到jj的距離(記為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]≤107

輸入樣例:

5

0 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
思路:因為要遍歷所有轉態,而本題的狀態太多(n最大為20,20個點組成的所有不同路徑為20(的全排列)即20的階乘種),無法在規定時間內完成,所以採用狀態壓縮,這裡起點和終點是固定的,有些路徑是無效的或可以去掉的(數值比較大的),所以只考慮當前哪些點走過和當前的位置在哪個點上(這裡所謂的狀態壓縮就是用二進位制的數表示狀態數,二進位制的每一位的數值0或1分別表示當前位的編號的點沒走過和走過了,這樣每一位都是0或1兩種情況,一共20位,所以有2的20次方個數對應2的20次方個狀態,再乘20個當前位置(終點),一共約2乘10的7次方,這樣的資料範圍就可以接受了),每次只由上乙個對應狀態(當前狀態去掉當前點的狀態)轉移過來,計算當前最優:

狀態轉移: dp[i][j]=min(dp[i][j],dp[i-(1《完整**:

#include #include #include #include using namespace std;

const int maxn=1<<20;

int n,dp[maxn][20],w[20][20];

int main()

}memset(dp,0x3f,sizeof(dp));//因為求最小值,所以初始化正無窮

dp[1][0]=0;//一開始在起點0上,所以用二進位制1表示當前第0位是1(即:0這個點走過了)

for(int i=0;i<1<>j&1)}}

}}

cout

}

最短Hamilton路徑(二進位制狀態壓縮dp)

給定一張 n 個點的帶權無向圖,點從 0 n 1 標號,求起點 0 到終點 n 1 的最短hamilton路徑。hamilton路徑的定義是從 0 到 n 1 不重不漏地經過每個點恰好一次。輸入格式 第一行輸入整數nn。接下來n行每行n個整數,其中第ii行第jj個整數表示點i到j的距離 記為a i,...

Hamilton哈密頓最短路徑 二進位制狀態壓縮

哈密頓最短路徑即為從起點到終點,計算出經過圖中所有點的最短路徑。點較少的情況 由於途中點較少,可能會直接想到暴力列舉所有點的全排列,然後計算最短距離,其時間複雜度為 o n n o n n o n n 但是如果使用動態規劃,列舉每個點被經過的狀態的話,那麼可以將時間複雜度降到 o n 2 2n o ...

最短Hamilton路徑

給定一張 n 個點的帶權無向圖,點從 0 n 1 標號,求起點 0 到終點 n 1 的最短hamilton路徑。hamilton路徑的定義是從 0 到 n 1 不重不漏地經過每個點恰好一次。輸入格式 第一行輸入整數n。接下來 n 行每行n個整數,其中第i行第j個整數表示點i到j的距離 記為a i,j...