最短Hamilton距离(二进制压状dp)

博客介绍了如何利用二进制动态规划算法解决从起点0到终点n-1的最短Hamilton路径问题。在不超过20个节点的带权无向图中,通过构建二维dp数组,初始化状态并应用状态转移方程,逐步计算出最短路径。算法复杂度为O(nn*2^n)。
摘要由CSDN通过智能技术生成

描述:给定一张n(n<=20)个点的带权无向图,点从0~n-1标号,求起点0到终点n-1的最短Hamilton路径。
Hamilton路径:从0~n-1重复不漏的经过每一个点恰好一次。
暴力做法:O(nn!)
二进制压状dp:O(n
n*2^n).
关键数组dp[1<<20][20];
在数组dp[i,j]中i通过二进制表示。i上的每一位数为一个节点,每一位数的值为0或1,表示未经过该节点和经过该节点。j为在遍历时每个节点是时,当时处于该节点,数组的值为目前0~j的最短路径。
例如:dp[11][1]=18
11的二进制是001011,目前的j是1(即我们目前处于1号节点),表示的是只经过节点0、3而到达1号节点(就是此时11的二进制只有0.1.3位数的值为1)的最短距离是18.
那么初始状态在0号节点的时候有dp[1][0]=0.
所以我们要求的就是dp[1 << n - 1][n - 1].

状态转移方程:
此时我们应该考虑从一个节点到另一个节点dp数组中的值会如何变化。先看一维数组,比如说上一个节点是k,此时我们到达了j节点,那么对于两个节点:
dp[i][j]=dp[i^(1<<j)][k]+w[j][k];
i^(1<<j)该公式表示将i的二进制表示中的第j位改为0,到达k节点时下一个要到达的节点时j故此时还未到达j。(w[j][k]代表j节点与k节点之间的距离)。

int dp[1 << 20][20], w[20][20];
int hamilton(int n) {
	memset(dp, inf, sizeof(dp));
	dp[1][0] = 0;
	for (int i = 1; i < 1 << n; i++)// 
	{
		for (int j = 0; j < n; j++) 
		{
			if (i >> j & 1) //判断i的二进制表示的第j位是否为1,如果为1,则表明按i的二进制的路线有到达j点的情况,否则没必要对此节点j进行判断。
			{
				for (int k = 0; k < n; k++) {
					if ((i ^ 1 << j) >> k & 1)//(i ^ 1 << j)表示上一个点的状态,那么上一个点的状态中第k位必须为1(即经过k节点)
						dp[i][j] = min(dp[i][j], dp[i ^ 1 << j][k] + w[k][j]);
				}
			}
		}
	}
	return dp[1 << n - 1][n - 1];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值