1004. Sightseeing trip
Memory Limit: 16 MB
Input
-1
” line.Output
No solution.
” in case there isn't any sightseeing route, or it contains the numbers of all crossing points on the shortest sightseeing route in the order how to pass them (i.e. the numbers x1 to xk from our definition of a sightseeing route), separated by single spaces. If there are multiple sightseeing routes of the minimal length, you can output any one of them. Sample
input | output |
---|---|
5 7 1 4 1 1 3 300 3 1 10 1 2 16 2 3 100 2 5 15 5 3 20 4 3 1 2 10 1 3 20 1 4 30 -1 |
1 3 5 2 No solution. |
解答如下:
2 using System.IO;
3
4 namespace Skyiv.Ben.Timus
5 {
6 // http://acm.timus.ru/problem.aspx?space=1&num=1004
7 sealed class T1004
8 {
9 static readonly int infinity = int.MaxValue;
10
11 static void Main()
12 {
13 while (Search(Console.Out, Read(Console.In))) ;
14 }
15
16 static int[,] Read(TextReader reader)
17 {
18 string[] ss = reader.ReadLine().Split();
19 if (ss.Length != 2) return null;
20 int n = int.Parse(ss[0]);
21 int[,] matrix = new int[n, n];
22 for (int i = 0; i < n; i++)
23 for (int j = 0; j < n; j++)
24 matrix[i, j] = infinity;
25 for (int i = int.Parse(ss[1]); i > 0; i--)
26 {
27 ss = reader.ReadLine().Split();
28 int a = int.Parse(ss[0]) - 1;
29 int b = int.Parse(ss[1]) - 1;
30 matrix[a, b] = matrix[b, a] = Math.Min(matrix[a, b], int.Parse(ss[2]));
31 }
32 return matrix;
33 }
34
35 static bool Search(TextWriter writer, int[,] matrix)
36 {
37 if (matrix == null) return false;
38 int n = matrix.GetLength(0), cnt = 0, dist = infinity;
39 int[] path = new int[n];
40 for (int i = 0; i < n - 1; i++)
41 for (int j = i + 1; j < n; j++)
42 {
43 int len = matrix[i, j];
44 if (len == infinity) continue;
45 matrix[i, j] = matrix[j, i] = infinity;
46 int[] prev = Dijkstra(matrix, i, j);
47 if (prev[n] == infinity || dist <= prev[n] + len) continue;
48 dist = prev[n] + len;
49 cnt = 0;
50 for (int k = j; k != -1; k = prev[k]) path[cnt++] = k + 1;
51 }
52 if (dist == infinity) writer.Write("No solution.");
53 else for (int i = 0; i < cnt; i++) writer.Write(path[i] + " ");
54 writer.WriteLine();
55 return true;
56 }
57
58 static int[] Dijkstra(int[,] matrix, int v1, int v2)
59 {
60 int n = matrix.GetLength(0);
61 bool[] used = new bool[n];
62 int[] dist = new int[n];
63 int[] prev = new int[n + 1];
64 for (int i = 0; i < dist.Length; i++) dist[i] = infinity;
65 dist[v1] = 0;
66 prev[v1] = -1;
67 while (true)
68 {
69 int k = -1;
70 for (int m = infinity, i = 0; i < n; i++)
71 if (!used[i] && dist[i] < m) m = dist[k = i];
72 prev[n] = (k == -1) ? infinity : dist[k];
73 if (k == -1 || k == v2) return prev;
74 for (int i = 0; i < n; i++)
75 if (matrix[k, i] != infinity && dist[i] > dist[k] + matrix[k, i])
76 dist[i] = dist[prev[i] = k] + matrix[k, i];
77 used[k] = true;
78 }
79 }
80 }
81 }
这道题目的意思是,给你一张地图,该地图上标明了若干旅游景点,以及各景点之间的道路及其里程。两个景点之间可以有多条道路,但是一条道路必须连接两个景点,而不能绕个圈又回到同一景点。现在你的任务是寻找满足以下条件的一条旅游线路:
- 该线路从某一景点出发后必须回到起点。
- 该线路至少必须包含三个景点。
- 该线路必须是所有可能的线路中最短的。
- 该线路不必须包含所有的景点。
上述程序中,第 16 到 33 行的 Read 方法读取输入的地图到矩阵 matrix 中。matrix 的元素表示各景点间的距离,在第 22 到 24 行中被初始化为无穷大,然后在第 25 到 31 行的 for 循环中读入各景点间的距离,并且如果某两个景点之间有多道路的话,只保留距离最短的一条(第 30 行)。该矩阵是对称的。
第 35 到 56 行的 Search 方法试图找出满足条件的旅游线路。该方法在第 40 到 51 行的双重循环中遍历各景点,如果某两个景点之间有道路相连的话(第 44 行),就在矩阵 matrix 中将该道路断开(第 45 行),然后调用 Dijkstra 方法寻找这两个景点之间的最短线路(第 46 行)。然后就判断并记录最短的环形的(加上刚被断开的道路)旅游线路(第 47 到 50 行)。第 52 到 54 行输出结果。注意,在第 45 行断开的道路不需要重新连接,因为在这次查找中已经是寻找最短线路了,下次不可能有经过这个道路的更短线路了。
第 58 到 79 行的 Dijkstra 方法使用著名的 Dijkstra 算法寻找景点 v1 到 v2 的最短线路。第 60 到 66 行进行必要的初始化工作,第 67 到 78 行的循环使用贪心技术寻找单源最短路径。数组 prev 记录所走的路径,而 prev[n] 表示该路径的长度。
返回目录
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述