1. 程式人生 > >【狀壓dp】【最短Hamilton路徑】

【狀壓dp】【最短Hamilton路徑】

題意:

       給出n個點,然後給出每兩個點之間的路徑,要求找到一條最短的路徑,從第1個點出發,到達最後一個點,中間所有的點都只經過一次,要求這條路徑是最短的。這稱為最短Hamilton路徑。

 

思路:

      因為n只有20個點,所以考慮狀壓dp,每一個狀態由兩個資料組成,一個是這個狀態最後停在了哪個點,一個是這個狀態之前走過了哪些路徑。

用f[1<<20][20]來記錄這個狀態下已經走過的最短路徑。

      那麼 f[i][j] = min{f[1<<j ^ i][k]+w[k][j]} 要求 k 和 j 這兩個點在 i 所記錄的路徑中出現過。

      然後從第一個狀態不斷往後進行更新即可。

 

程式碼:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define rep(i,a,b) for(int i = a; i <= b; i++)
using namespace std;

int w[25][25],n;
int f[1<<21][25];

void solve()
{
	memset(f,0x3f,sizeof f);
	f[1][0] = 0;
	rep(i,0,(1<<n)-1)
	{
		rep(j,0,n-1)
			if(1<<j & i) //這個點被走過了,列舉結束點
				rep(k,0,n-1) //由哪個點更新而來	
					if(1<<k & i)
						f[i][j] = min(f[i][j],f[i ^ 1<<j][k]+w[k][j]);
	}
	printf("%d\n",f[(1<<n)-1][n-1]);
}

int main()
{
	while(~scanf("%d",&n))
	{
		rep(i,0,n-1)
			rep(j,0,n-1)
				scanf("%d",&w[i][j]);
		solve();
	}
	return 0;
}