PAT Advanced 1150 Travelling Salesman Problem (25 )

题目描述

在这里插入图片描述

Input Specification:

在这里插入图片描述

Output Specification:

在这里插入图片描述

Sample Input:

在这里插入图片描述

Sample Output:

在这里插入图片描述

解题思路

TS Cycle需要具备:闭合,每个city都visit过。
TS Simple Cycle则是在TS的Cycle的基础上,约束每个city只经过一次。
Not a TS Cycle则是除外以上两种情况剩余的情况。

Code

  • AC代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 200+10;
int dis[maxn][maxn];
int pathLength;
bool isTsCycle, isTsSimple;
void solve(vector<int> cycle, int N) {
	int len = cycle.size();
	int cnt[N+1];
	memset(cnt, 0, sizeof(cnt));
	for(int i = 1; i<len; i++) {
		int u = cycle[i-1], v = cycle[i];
		if(dis[u][v] == -1) {
			pathLength = -1;
			isTsCycle = false;
			return ;
		} else {
			pathLength += dis[u][v];
		}
		cnt[v]++;
	}
	if(cycle[0] != cycle[len-1]) {
		isTsCycle = false;
		return ;
	}
	for(int i = 1; i<=N; i++) {
		if(!cnt[i]) {
			isTsCycle = false;
			return ;
		} else if(cnt[i] > 1) {
			isTsSimple = false;
		}
	}
}

int main() {
	//freopen("in.txt", "r", stdin);
	int N, M, u, v, d;
	cin >> N >> M;
	memset(dis, -1, sizeof(dis));
	for(int i = 0; i<M; i++) {
		cin >> u >> v >> d;
		dis[u][v] = dis[v][u] = d;
	}
	int k, num, shortestDis, idx = -1;
	cin >> k;
	for(int i = 1; i<=k; i++) {
		cin >> num;
		vector<int> cycle(num);
		for(int j = 0; j<num; j++) {
			cin >> cycle[j];
		}
		pathLength = 0;
		isTsCycle = true, isTsSimple = true; 
		solve(cycle, N);
		cout << "Path " << i << ": ";
		pathLength != -1 ? cout << pathLength : cout << "NA";
		if(isTsCycle) {
			if(isTsSimple) {
				cout << " (TS simple cycle)\n";
			} else {
				cout << " (TS cycle)\n";
			}
			if(idx == -1 || pathLength < shortestDis){
				shortestDis = pathLength, idx = i;
			}
		} else {
			cout << " (Not a TS cycle)\n";
		}
	}
	cout << "Shortest Dist(" << idx << ") = " << shortestDis << '\n';
	return 0;
}

总结

  1. memset的正确用法
    //函数原型
    extern void *memset(void *buffer, int c, int count)        
    //buffer:为指针或是数组,
    //c:是赋给buffer的值,
    //count:是buffer的长度.注意计算buffer的长度时,不是指数组大小,而是指buffer数组所占字节数,比如buffer是int数组,
    //那么count = 4*buffer.length();
    //或者count = sizeof(buffer);
  1. 关于memset可以初始化的值
  • memset的正规用法是只能用来初始化char类型的数组的,也就是说,它只接受0x00-0xFF的赋值。因为char是1字节,memset是按照字节赋值的,相当于把每个字节都设为那个数,所以char型的数组可赋任意值
  • 对于也常用的int类型,int是4个字节,
    当memset(,1,sizeof())时,1相当于ASCII码的1,1转为二进制00000001,当做一字节,一字节8位,int为4字节,所以初始化完每个数为00000001000000010000000100000001 = 16843009;
    当memset(,0xff,sizeof())时,0xff转为二进制11111111,int为4字节所以最后为11111111111111111111111111111111为-1。(化为二进制补位,然后再赋值)。
    0的二进制位000000000000000000000000000000000,-1的二进制就是11111111111111111111111111111111,所以memset可以直接初始化(0,-1)
  • memset无穷大,一般用0x3f3f3f3f
    0x3f3f3f3f的十进制是1061109567,也就是10^9级别的(和0x7fffffff一个数量级)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值