【状压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;
}

猜你喜欢

转载自blog.csdn.net/qq_41552508/article/details/83280970