HDU3001&BUCU5974——旅行商变形2(英文版Travelling)——题解
Posted Tisfy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU3001&BUCU5974——旅行商变形2(英文版Travelling)——题解相关的知识,希望对你有一定的参考价值。
传送门
旅行商变形2
时间限制:3秒
空间限制:256M
题目描述
三笠阿卡曼决定参观 n n n 个城市,它要参观所有城市,不介意哪座册城市作为她的起点。
有 m m m 条道路照常收费,但她不想去一座城市超过 2 2 2 次,想把费用降到最低。
输入描述
输入包括几个测试用例。
对于每个测试用例:
第一行包含两个整数 n ( 1 ≤ n ≤ 10 ) n(1\\leq n\\leq10) n(1≤n≤10)和 m m m,表示 n n n 个城市、 m m m 条道路。
接下来 m m m 行,每行都包含三个整数 a 、 b a、b a、b 和 c ( 1 ≤ a , b ≤ n ) c(1\\leq a, b\\leq n) c(1≤a,b≤n),表示在 a a a 和 b b b 之间有一条道路,费用是 c c c
输出描述
对于每个测试用例,都单行输出应支付的最低费用。
若找不到这样的路线,输出 − 1 -1 −1。
样例一
输入
2 1
1 2 100
3 2
1 2 40
2 3 50
3 3
1 2 3
1 3 4
2 3 10
输出
100
90
7
题目分析
本题是旅行商问题的变形,热河一个城市都可以作为源点,且走完每个城市即可,不需要回到源点。
每个城市最多经过两次,最少经过一次,求走完所有城市的最小费用。
该问题中,每个城市有三种状态,可用三进制表示(0表示未访问,1表示已访问1次,2表示已访问2次)
解题思路
本题最多有10个城市,每个都有3中取值,共 3 10 = 59050 3^10=59050 310=59050种状态。
例如有5坐城市, ( 11202 ) 3 (11202)_3 (11202)3表示第1个城市被访问了2次,第2个城市被访问了0次,第3个城市被访问了2次,第4、5个城市各被访问了1次。
状态表示:dp[S][u]表示当前状态为S时从u除法访问剩余所有城市的最小费用。
状态转移方程:dp[S][u]等于状态为S-u时从v出发访问剩余所有城市的最小费用加上u到v的边值。若u有多个未被访问的邻接点v,则取其最小值。dp[S][u]=min(dp[S][u], dp[S-u][v]+d[u][v])
边界条件:dp[tri[i]][i]=0,初始化状态为tri[i]时,从i出发的最小费用为0。
tri[i]表示第i个节点已被访问1次,其他节点未被访问。tri[i]表示的三进制数的第i位为1,其他位位0.tri[i]可用用一个数组表示,其表达的含义为三进制,但在该程序中被赋值为十进制数。例如tri[3]表示的三进制数的第3位是1,其余位是0,即 ( 100 ) 3 (100)_3 (100)3,其对应的十进制数 ( 100 ) 3 = 1 × 3 2 + 0 × 3 1 + 0 × 3 0 = 9 (100)_3=1\\times3^2+0\\times3^1+0\\times3^0=9 (100)3=1×32+0×31+0×30=9, t r i [ 3 ] = 9 tri[3]=9 tri[3]=9。对其他节点也如此处理,得到数组int tri[12]=0, 1, 3, 9, 27, 81, 243, 729, 2187, 19683, 59048。
dp[9][3]表示在只有第3个城市已被访问的状态下,从3出发走完剩余城市的最小费用。
AC代码
#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
int dig[60000][11];
int dp[60000][11];
int tri[12];
int edge[11][11];
void init()
tri[1] = 1;
for (int i = 2; i < 12; i++)
tri[i] = tri[i - 1] * 3;
for (int i = 0; i < 59050; i++) // 预处理状态S的第j位
int t = i;
for (int j = 1; j <= 10; j++)
dig[i][j] = t % 3;
t /= 3;
if (!t)
break;
int main()
init();
int n, m;
while (cin >> n >> m)
for (int i = 0; i <= tri[n + 1]; i++)
for (int j = 0; j <= n; j++)
dp[i][j] = 1e8;
for (int i = 1; i <= n; i++)
dp[tri[i]][i] = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
edge[i][j] = 1e8;
while (m--)
int u, v, c;
scanf("%d%d%d", &u, &v, &c);
edge[u][v] = edge[v][u] = min(edge[u][v], c);
int ans = 1e8;
for (int S = 0; S < tri[n + 1]; S++)
bool visit_all = true;
for (int u = 1; u <= n; u++)
if (dig[S][u] == 0)
visit_all = false;
continue;
for (int v = 1; v <= n; v++)
if (dig[S][v] == 0)
continue;
dp[S][u] = min(dp[S][u], dp[S - tri[u]][v] + edge[u][v]);
if (visit_all)
for (int u = 1; u <= n; u++)
ans = min(ans, dp[S][u]);
cout << ans << endl;
return 0;
原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/122634759
以上是关于HDU3001&BUCU5974——旅行商变形2(英文版Travelling)——题解的主要内容,如果未能解决你的问题,请参考以下文章