数据结构图 —— 编程作业 05 :Saving James Bond - Hard Version

Posted 大彤小忆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构图 —— 编程作业 05 :Saving James Bond - Hard Version相关的知识,希望对你有一定的参考价值。

  题目描述: 在电影"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的测试效果如下图所示。

在这里插入图片描述

以上是关于数据结构图 —— 编程作业 05 :Saving James Bond - Hard Version的主要内容,如果未能解决你的问题,请参考以下文章

数据结构树 —— 编程作业 05 :是否同一棵二叉搜索树

pta编程题19 Saving James Bond 2

pta 编程题16 Saving James Bond - Easy Version

数据结构 07-图5 Saving James Bond

数据结构图 —— 编程作业 03 :六度空间

数据结构图 —— 编程作业 07 :公路村村通