数据结构系列内容的学习目录 → \rightarrow →浙大版数据结构学习系列内容汇总。
题目描述: 在电影"Live and Let Die"(Live and Let Die)中有一个情节,世界上最著名的间谍007被毒贩抓到一个鳄鱼池中心的小岛上,他用了一种极为大胆的方法逃脱 —— 他跳到离他最近的鳄鱼的头上,在鳄鱼还没意识到发生了什么之前,又跳到下一个鳄鱼的头上… …最后,他在最后一条鳄鱼咬住他之前上岸,成功逃脱!
假设鳄鱼池是长宽为100米的方形,中心坐标为 (0, 0),且东北角坐标为 (50, 50)。池心岛是以 (0, 0) 为圆心、直径15米的圆。给定池中分布的鳄鱼的坐标、以及007一次能跳跃的最大距离,需要告诉他到达其中一个河岸的最短路径,路径的长度是007必须要跳跃的次数。
输入格式: 每个输入文件包含一个测试用例。
首先第一行给出两个正整数:鳄鱼数量 N(≤100)和007一次能跳跃的最大距离 D。
随后 N 行,每行给出一条鳄鱼的坐标。注意:不会有两条鳄鱼待在同一个点上。
输出格式: 对于每个测试用例,如果007能够逃脱,在一行中输出他必须完成的最小跳跃次数。
然后从下一行开始,在每行中输出从池心岛到岸边的路径上每条鳄鱼的位置(x, y)。
如果007不可能逃跑,则他的跳跃次数为0。
如果有多条最短路径,只输出第一步跳跃距离最短的那条路径,以保证唯一。
输入样例1:
17 15 10 -21 10 21 -40 10 30 -50 20 40 35 10 0 -10 -25 22 40 -40 -30 30 -10 22 0 11 25 21 25 10 10 10 10 35 -30 10
输出样例1:
4 0 11 10 21 10 35
输入样例2:
4 13 -12 12 12 12 -12 -12 12 -12
输出样例2:
0
代码实现:
#include<iostream> using namespace std; #include<queue> #include<stack> #include<algorithm> int n, m; #define MINLEN 42.5 #define MaxVertex 105 struct Pointer { // 存鳄鱼位置信息 int x; // 横坐标 int y; // 纵坐标 }point[MaxVertex]; bool answer = false; // 记录007能否安全逃生 bool visited[MaxVertex] = { false }; // 判断当前点是否被访问过 int path[MaxVertex] = { -1 }; // 记录跳跃过程中踩过的鳄鱼 // 判断从当前点能否跳到岸上 bool isSave(int v) { if ((point[v].x - m <= -50) || (point[v].x + m >= 50) || (point[v].y - m <= -50) || (point[v].y + m >= 50)) return true; return false; } // 判断2个点距离是否在跳跃能力内 bool Jump(int v1, int v2) { int p1 = pow(point[v1].x - point[v2].x, 2); int p2 = pow(point[v1].y - point[v2].y, 2); int r = m * m; if (p1 + p2 <= r) return true; return false; } // 当007处于孤岛时,第一次可以选择跳的鳄鱼 int FirstJump(int v) { int p1 = pow(point[v].x, 2); int p2 = pow(point[v].y, 2); int r = (m + 7.5) * (m + 7.5); if (p1 + p2 <= r) { return p1 + p2; } return 0; } bool cmp(int a, int b) { return FirstJump(a) < FirstJump(b); } // 用BFS来判断最少要踩几个鳄鱼才能上岸 void BFS() { int b[MaxVertex]; queue<int>q; // 将第一步能踩到的鳄鱼按距离从小到大的顺序进队列,因为输出结果要保证在踩的鳄鱼数量相等的情况下,输出第一步距离最短的 for (int i = 0; i < n; i++) b[i] = i; sort(b, b + n, cmp); // 按照第一步的距离排序 int last; for (int i = 0; i < n; i++) { if (FirstJump(b[i])) // 能跳上去! { q.push(b[i]); visited[b[i]] = true; // 指向当前层数最后一个数 last = b[i]; } } int step = 2; // 记录最少要跳跃的次数 int tail = 0; while (!q.empty()) { int p = q.front(); q.pop(); if (isSave(p)) { int k = 1; stack<int> s; cout << step << endl; while (k < step) { s.push(p); p = path[p]; k++; } while (!s.empty()) { p = s.top(); s.pop(); cout << point[p].x << " " << point[p].y << endl; } return; } for (int i = 0; i < n; i++) { if (!visited[i] && Jump(p, i)) // 没踩过并且能跳到 { q.push(i); path[i] = p; // 记得当前进队节点的父节点 visited[i] = true; tail = i; // 指向下一层的最后一个元素 } } if (last == p) // 即将进入下一层 { step += 1; last = tail; } } if (q.empty()) // 如果队列为空 说明没跳出去 { cout << "0" << endl; } } int main() { cin >> n >> m; for (int i = 0; i < n; i++) { cin >> point[i].x >> point[i].y; } if (m >= MINLEN) // 可以直接从孤岛上跳到岸上,直接输出 { cout << "1" << endl; return 0; } BFS(); system("pause"); return 0; }
测试:
- 测试1:输入样例1的测试效果如下图所示。
- 测试2:输入样例2的测试效果如下图所示。