【ybtoj 状压DP课堂过关】【AcWing 91】最短 Hamilton 路径 &【例题2】最短路径

【例题2】最短 Hamilton 路径 & 最短路径


Link

ybtoj【状压DP课堂过关】【例题2】最短路径
AcWing 【91】最短 Hamilton 路径
题面//因为不知道侵不侵权所以就是题面是私密的,有账号的直接看转送门就可了


题目大意

给出n个点,和n个点之间边的长度
找出最短的一条路,遍布所有点(不能重复走)


解题思路

我爱状压!!!
之前在jz做过一个高阶版
所以这题做起来还挺顺的

设 f[i][j] 为遍布状态为 i,最后一个遍布的点是 j 的最短路径
f [ i ] [ j ] = m i n ( f [ i ] [ j ] , f [ i   x o r   ( 1 < < j − 1 ) ] [ k ] + s [ k ] [ j ] ) f[i][j] = min(f[i][j], f[i\ xor\ (1 << j - 1)][k] + s[k][j]) f[i][j]=min(f[i][j],f[i xor (1<<j1)][k]+s[k][j])
基础状压真的太喜欢了)


Code

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

int n, maxn;
int s[25][25], f[1050000][20];

int main() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i ++)  //本人不太喜欢0开始,所以就1 ~ n了
		for(int j = 1; j <= n; j ++)
			scanf("%d", &s[i][j]);
	int maxn = (1 << n) - 1;
	memset(f, 0x7f, sizeof(f));
	f[1][1] = 0;  //初始化,起点是1
	for(int i = 2; i <= maxn; i ++) {
		for(int j = 1; j <= n; j ++) {
			if(!(i & (1 << j - 1))) continue;  //i中必须遍布了j
			for(int k = 1; k <= n; k ++) {
				if(j == k) continue;  
				if(!(i & (1 << k - 1))) continue;  //i中必须遍布k
				f[i][j] = min(f[i][j], f[i ^ (1 << j - 1)][k] + s[k][j]);
			}
		}
	}
	printf("%d", f[maxn][n]);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值