算法 图2 Saving James Bond - Easy Version

全部每周作业和视频思考题答案和解析 见 浙江大学 数据结构 思考题+每周练习答案汇总

题目:This time let us consider the situation in the movie "Live and Let Die" in which James Bond, the world's most famous spy, was captured by a group of drug dealers. He was sent to a small piece of land at the center of a lake filled with crocodiles. There he performed the most daring action to escape -- he jumped onto the head of the nearest crocodile! Before the animal realized what was happening, James jumped again onto the next big head... Finally he reached the bank before the last crocodile could bite him (actually the stunt man was caught by the big mouth and barely escaped with his extra thick boot).

Assume that the lake is a 100 by 100 square one. Assume that the center of the lake is at (0,0) and the northeast corner at (50,50). The central island is a disk centered at (0,0) with the diameter of 15. A number of crocodiles are in the lake at various positions. Given the coordinates of each crocodile and the distance that James could jump, you must tell him whether or not he can escape.

这一次让我们来考虑电影《生死存亡》中的情形,在这部电影中,世界上最著名的间谍詹姆斯·邦德被一群毒贩抓获。他被送到了一个充满鳄鱼的湖中心的一小块土地上。他在那里做了最大胆的逃跑动作——他跳到了最近的鳄鱼头上!在动物意识到发生了什么之前,詹姆斯又跳到了下一个大脑袋上。。。最后,在最后一条鳄鱼咬他之前,他终于到了岸边(实际上,这个特技演员被大嘴抓住了,用他特别厚的靴子勉强逃脱)。

假设这个湖是100×100平方的。假设湖心位于(0,0),东北角位于(50,50)。中心岛是一个以(0,0)为中心的圆盘,直径为15。许多鳄鱼在湖中的不同位置。考虑到每只鳄鱼的坐标和詹姆斯能跳的距离,你必须告诉他他是否能逃脱。

Input Specification:

Each input file contains one test case. Each case starts with a line containing two positive integers N (≤100), the number of crocodiles, and D, the maximum distance that James could jump. Then N lines follow, each containing the (x,y) location of a crocodile. Note that no two crocodiles are staying at the same position.

Output Specification:

For each test case, print in a line "Yes" if James can escape, or "No" if not.

Sample Input 1:

14 20
25 -15
-25 28
8 49
29 15
-35 -2
5 28
27 -29
-8 -28
-20 -35
-25 -20
-13 29
-30 15
-35 40
12 12

Sample Output 1:

Yes

Sample Input 2:

4 13
-12 12
12 12
-12 -12
12 -12

Sample Output 2:

No

解答:

虽然我实在懒得解救007,不过为了锻炼编程能力还是勉强去解救一下吧。

首先考虑建图还是不建图。如果不存储图的话,每次跳跃之前都要判断能否跳到。而如果存储图的话,可以将所有结点的连通性存储下来,这样可以避免每次计算,运行速度更快,但更占空间。

其实这个程序和上个题没什么太大差别,我就是直接拿上个题的程序改的,我们只需要提前先把每两个点能够相连计算出来即可。

扫描二维码关注公众号,回复: 10618587 查看本文章

注意在这个数组中,第一个表示中心岛,即索引0,最后末尾表示岸边,即索引N+1。索引从1到N表示这N个鳄鱼。

计算方法:

void generateGra(int E,int D) {
	//E为鳄鱼的数量
	for (int i = 1;i <= E;i++) {
		int a, b;
		cin >> a >> b;
		Cordlx[i] = a;
		Cordly[i] = b;
	}
	//判断能不能从岛跳到鳄鱼背上
	for (int i = 1;i <= E;i++) {
		if ((15/2.0 + D)*(15/2.0 + D) >= pow2(Cordlx[i])+ pow2(Cordly[i])) {
			//能跳到该鳄鱼背上
			Graph[0][i] = 1;
			Graph[i][0] = 1;
		}
	}
	//判断能不能从一条鳄鱼跳到另一条鳄鱼
	for (int i = 1;i <= E;i++) {
		for (int j = i + 1;j <= E;j++) {
			if (pow2(D) >= (pow2(Cordlx[i]-Cordlx[j])+pow2(Cordly[i] - Cordly[j]))) {
				Graph[i][j] = 1;
				Graph[j][i] = 1;
			}
		}
	}
	//计算是否能上岸
	for (int i = 1;i <= E;i++) {
		if (50 - Max(Cordlx[i], Cordly[i]) <= D || 50 + Min(Cordlx[i], Cordly[i]) <= D) {
			Graph[E + 1][i] = 1;
			Graph[i][E + 1] = 1;
		}
	}

	/*
	for (int i = 0;i <= E+1;i++) {
		for (int j = 0;j <= E+1;j++) {
			cout << Graph[i][j] << " ";
		}
		cout << endl;
	}*/

}

最后面屏蔽的代码是把图输出,查看我们计算的结果是否正确。

后面在遍历的时候也会输出遍历的顺序,我先把测试结果放上来。测试数据就用的题目中给的。

可以看到,从岸边跳到第一个鳄鱼,然后再跳到第7个鳄鱼就截止了。

然后再去进行第二个递归。为了完整性就算我能跳到岸边我也继续进行递归。

全部代码放上,测试可直接通过:

#include <iostream>
#include <map>
#include <queue>
#include <vector>
#include <string>
using namespace std;
//0代表中心岛,最后一个代表岸边
int Graph[102][102];
int Cordlx[102];
int Cordly[102];
bool visit[102];
void initGraph(int N);
void recovGraph(int N);
void generateGra(int E,int D);
void ErgDFS(int N);

int main(void) {
	int N,D;
	cin >> N >> D;
	initGraph(N);
	generateGra(N,D);

	ErgDFS(N);
	system("pause");
	return 0;
}

void initGraph(int N) {
	for (int i = 0;i <= N+1;i++) {
		visit[i] = 0;
		for (int j = 0;j <= N+1;j++) {
			Graph[i][j] = 0;
			if (i == j) {
				Graph[i][j] = 1;
			}
		}	
	}
}
void recovGraph(int N) {
	for (int i = 0;i < N;i++) {
		visit[i] = 0;
	}
}

int pow2(int a) {
	return a*a;
}
int Max(int a, int b) {
	return a > b ? a : b;
}
int Min(int a, int b) {
	return a < b ? a : b;
}
void generateGra(int E,int D) {
	//E为鳄鱼的数量
	for (int i = 1;i <= E;i++) {
		int a, b;
		cin >> a >> b;
		Cordlx[i] = a;
		Cordly[i] = b;
	}
	//判断能不能从岛跳到鳄鱼背上
	for (int i = 1;i <= E;i++) {
//注意直径是15,半径得除以2
		if ((7.5 + D)*(7.5 + D) >= pow2(Cordlx[i])+ pow2(Cordly[i])) {
			//能跳到该鳄鱼背上
			Graph[0][i] = 1;
			Graph[i][0] = 1;
		}
	}
	//判断能不能从一条鳄鱼跳到另一条鳄鱼
	for (int i = 1;i <= E;i++) {
		for (int j = i + 1;j <= E;j++) {
			if (pow2(D) >= (pow2(Cordlx[i]-Cordlx[j])+pow2(Cordly[i] - Cordly[j]))) {
				Graph[i][j] = 1;
				Graph[j][i] = 1;
			}
		}
	}
	//计算是否能上岸
	for (int i = 1;i <= E;i++) {
		if (50 - Max(Cordlx[i], Cordly[i]) <= D || 50 + Min(Cordlx[i], Cordly[i]) <= D) {
			Graph[E + 1][i] = 1;
			Graph[i][E + 1] = 1;
		}
	}

	/*
	for (int i = 0;i <= E+1;i++) {
		for (int j = 0;j <= E+1;j++) {
			cout << Graph[i][j] << " ";
		}
		cout << endl;
	}*/

}

int flag = 0;
void DFS(int i,int N)
{   
	visit[i] = 1;
	//cout << i << " " << endl;
	if (Graph[i][N + 1] == 1) {
		flag = 1;
		return;
	}
	for (int k = 1;k <= N;k++) {
		if (Graph[i][k] == 1 && visit[k] == 0) {
			visit[k] = 1;
			DFS(k,N);		
		}
	}		
}
void ErgDFS(int N) {
	for (int i = 1;i <= N;i++) {
		if (Graph[0][i]==1 && visit[i] == 0) {
			DFS(i,N);
			//cout << endl;
		}	

	}
	if (flag == 1)cout << "Yes";
	else cout << "No";
}


测试结果:

注意判断是否能上岸的技巧:只要横纵坐标里最大的那个数到50的距离小于D,或者最小的那个数到-50的距离小于D,就能从那个鳄鱼跳到岸上。

发布了174 篇原创文章 · 获赞 394 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/tiao_god/article/details/105223807