給定一張 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...