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;
}
总结
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);
- 关于
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一个数量级)