UVa 116 - Unidirectional TSP

Contents

  1. 1. Problem
  2. 2. Solution
  3. 3. Code

Problem

題目網址
中文網址

Solution

因為要求字典序最小的路徑,所以從最右行做到左,最後在找最小權重時,只需要選從第一列開始最先找到的,就會是最小字典序。

對每個位置做 DP,(i,j) 會有 3 個地方可以到此點,選其中權重最小的。直到做完第一行,再找權重最小的路徑輸出即可。

Code

UVa 116116 - Unidirectional TSP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include<cstdio>
#define M 10
#define N 100

inline int MIN(int a, int b);
int main()
{
int n, m;
int map[M][N] = {}, path[M][N] = {}, dis[M][N] = {};
while (scanf("%d%d", &m, &n) != EOF)
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
scanf("%d", &map[i][j]);

for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
dis[i][j] = 1e9;

//初始化 到最後一行 的 dis
for (i = 0; i < m; i++)
dis[i][n - 1] = map[i][n - 1];

//從右邊開始走到 (j,i) 的最短路
for (i = n - 2; i >= 0; i--)//col
{
for (j = 0; j < m; j++)//row
{
int a, b, c, temp, min;

//3 種走法
a = (j + m - 1) % m;
b = j;
c = (j + 1) % m;

//找最短路
temp = MIN(dis[a][i + 1], dis[b][i + 1]);
if (temp == 1)
min = a;
else if (temp == -1)
min = b;
else
min = a < b ? a : b;//選字典序小的

temp = MIN(dis[min][i + 1], dis[c][i + 1]);
if (temp == -1)
min = c;
else if (!temp)
min = min < c ? min : c;//選字典序小的

//到 (j,i) 的最短路
dis[j][i] = dis[min][i + 1] + map[j][i];

//到 (j,i) 最短路的上一點是在第 min 列
path[j][i] = min;
}
}

int row, min = 1e9;
//找第一行 dis 最小的,注意字典序
for (i = 0; i < m; i++)
if (dis[i][0] < min)
{
min = dis[i][0];
row = i;
}

for (i = 0; i < n - 1; i++)
{
printf("%d ", row + 1);
row = path[row][i];
}

printf("%d\n%d\n", row + 1, min);
}

return 0;
}
int MIN(int a, int b)
{
if (a < b)
return 1;
else if (a > b)
return -1;
else
return 0;
}