P10447 最短 Hamilton 路径

Description

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

Analysis

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

d p S , v dp_{S,v} dpS,v 表示经过的点集合为 S S S,且当前所在的点为 u u u 时的路径长度。
状态转移方程显然为 d p S , v = min ⁡ u ∈ S { d p S − { 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 的套路,外层枚举 S S S,第二层枚举 v v v(注意判断是否和 S S S 矛盾),第三层枚举 u ∈ S u \in S uS 进行转移。

这里可以进行一个常数优化,枚举 S S S 时,只需要枚举包含 1 1 1 号点的即可(另外 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、付费专栏及课程。

余额充值