PAT甲级1150 Travelling Salesman Problem//遍历图

The “travelling salesman problem” asks the following question: “Given a list of cities and the distances between each pair of cities, what is the shortest possible route that visits each city and returns to the origin city?” It is an NP-hard problem in combinatorial optimization, important in operations research and theoretical computer science. (Quoted from “https://en.wikipedia.org/wiki/Travelling_salesman_problem”.)
In this problem, you are supposed to find, from a given list of cycles, the one that is the closest to the solution of a travelling salesman problem.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive integers N (2<N≤200), the number of cities, and M, the number of edges in an undirected graph. Then M lines follow, each describes an edge in the format City1 City2 Dist, where the cities are numbered from 1 to N and the distance Dist is positive and is no more than 100. The next line gives a positive integer K which is the number of paths, followed by K lines of paths, each in the format:
n C1 C2 … Cn
​where n is the number of cities in the list, and Ci’s are the cities on a path.

Output Specification:

For each path, print in a line Path X: TotalDist (Description) where X is the index (starting from 1) of that path, TotalDist its total distance (if this distance does not exist, output NA instead), and Description is one of the following:

  • TS simple cycle if it is a simple cycle that visits every city;
  • TS cycle if it is a cycle that visits every city, but not a simple cycle;
  • Not a TS cycle if it is NOT a cycle that visits every city.

Finally print in a line Shortest Dist(X) = TotalDist where X is the index of the cycle that is the closest to the solution of a travelling salesman problem, and TotalDist is its total distance. It is guaranteed that such a solution is unique.

Sample Input:

6 10
6 2 1
3 4 1
1 5 1
2 5 1
3 1 8
4 1 6
1 6 1
6 3 1
1 2 1
4 5 1
7
7 5 1 4 3 6 2 5
7 6 1 3 4 5 2 6
6 5 1 4 3 6 2
9 6 2 1 6 3 4 5 2 6
4 1 2 5 1
7 6 1 2 5 4 3 1
7 6 3 2 5 4 1 6

Sample Output:

Path 1: 11 (TS simple cycle)
Path 2: 13 (TS simple cycle)
Path 3: 10 (Not a TS cycle)
Path 4: 8 (TS cycle)
Path 5: 3 (Not a TS cycle)
Path 6: 13 (Not a TS cycle)
Path 7: NA (Not a TS cycle)
Shortest Dist(4) = 8

思路

看到题目一直不知道怎么做,这似乎是一个从一个点出发,找到最短的回到原点的路径,又不是最小生成树,也不是全源最短路径。没有一个已知算法适合做这个。没办法只好看大神思路,看了以后发现好像是自己想的太复杂了…

  • TS simple cycle 判断给定路径是否遍历了所有城市,要求起点和终点相同,只有起点重复了一次,只是看是否是最简单的环,并不管路径长度
  • TS cycle 就是判断给定路径是不是遍历了所有城市,不要求是最简单的环,即有城市访问多次
  • Not a TS cycle 是看给定路径有没有访问所有城市,起点终点一不一样,有没有路走不通
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
const int INF = INT_MAX;
int N, M;
int G[201][201];
bool vis[201] = {false};
void judge();
int main()
{
	fill(G[0], G[0] + 201 * 201, INF);
	cin >> N >> M;
	for (int i = 0; i < M; i++)
	{
		int c1, c2, d;
		cin >> c1 >> c2 >> d;
		G[c1][c2] = G[c2][c1] = d;
	}
	int K, path[1000];
	cin >> K;
	int IndexMin = -1, MinDist = INF;
	for (int i = 1; i <= K; i++)
	{
		fill(vis, vis + 201, 0);
		int n;
		cin >> n;
		for (int j = 0; j < n; j++)
		{
			cin >> path[j];
			vis[path[j]] = 1;
		}
		//判断有没有全部访问
		bool VisitAll = true;
		for (int j = 1; j <= N; j++)
			if (!vis[j])
				VisitAll = false;
		//计算总路径长度
		int totalDist = 0;
		for (int j = 1; j < n; j++)
		{
			if (G[path[j - 1]][path[j]] == INF)
			{
				//存在路径不通说明不能做到全部访问
				VisitAll = false;
				totalDist = -1;
				break;
			}
			else
				totalDist += G[path[j - 1]][path[j]];
		}
		cout << "Path " << i << ": ";
		
		//注意这里条件是totalDist != -1,而不是VisitAll == true
		//后者会忽略没有访问所有城市,但也形成循环的情况,比如样例的1251
		if (totalDist != -1)
			cout << totalDist << " ";
		else
			cout << "NA ";
		if (!VisitAll || path[0] != path[n - 1])
			cout << "(Not a TS cycle)" << endl;
		else
		{
			if (totalDist < MinDist)
			{
				MinDist = totalDist;
				IndexMin = i;
			}
			if (n == N + 1)
				cout << "(TS simple cycle)" << endl;
			else
				cout << "(TS cycle)" << endl;
		}
	}
	cout << "Shortest Dist(" << IndexMin << ") = " << MinDist << endl;
	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
牙科就诊管理系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线查看数据。管理员管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等功能。牙科就诊管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 管理员在后台主要管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等。 牙医列表页面,此页面提供给管理员的功能有:查看牙医、新增牙医、修改牙医、删除牙医等。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。药品管理页面,此页面提供给管理员的功能有:新增药品,修改药品,删除药品。药品类型管理页面,此页面提供给管理员的功能有:新增药品类型,修改药品类型,删除药品类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值