P10447 最短 Hamilton 路径

Description

给定一张 nnn 个点的带权完全无向图,求出从 111nnn 经过每个点恰好一次的最短路。

Analysis

由于 n≤20n \le 20n20,可以选用 状压dp 来解决问题。

dpS,vdp_{S,v}dpS,v 表示经过的点集合为 SSS,且当前所在的点为 uuu 时的路径长度。
状态转移方程显然为 dpS,v=min⁡u∈S{dpS−{v},u+w(u,v)}dp_{S,v}=\min\limits_{u \in S} \{ dp_{S-\{v\},u} + w(u,v) \}dpS,v=uSmin{dpS{v},u+w(u,v)}

接下来按照 状压dp 的套路,外层枚举 SSS,第二层枚举 vvv(注意判断是否和 SSS 矛盾),第三层枚举 u∈Su \in SuS 进行转移。

这里可以进行一个常数优化,枚举 SSS 时,只需要枚举包含 111 号点的即可(另外 S={}S=\{\}S={}S={1}S=\{1\}S={1} 显然也无用)。

Code

// Problem: P10447 最短 Hamilton 路径
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P10447
// Memory Limit: 512 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;

using i64 = long long;
const int INF = 1e9;

template<class T>
bool chmax(T &a, const T &b){
	if(a < b){ a = b; return true; }
	return false;
}

template<class T>
bool chmin(T &a, const T &b){
	if(a > b){ a = b; return true; }
	return false;
}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	int n;
	cin >> n;
	
	int up = 1 << n;
	vector dis(n, vector<int>(n));
	vector dp(up, vector<int>(n, INF));
	
	for (auto &x : dis)
	    for (auto &y : x) cin >> y;
	
	dp[1][0] = 0;
	for (int S = 3; S < up; S += 2)
	    for (int v = 1; v < n; v++) if ((S >> v) & 1)
	        for (int u = 0; u < n; u++)
	            if ((S >> u) & 1) chmin(dp[S][v], dp[S - (1 << v)][u] + dis[u][v]);
	cout << dp[up - 1][n - 1] << endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值