拯救007——图的遍历和应用

在老电影“007之生死关头”(Live and Let Die)中有一个情节,007被毒贩抓到一个鳄鱼池中心的小岛上,他用了一种极为大胆的方法逃脱 —— 直接踩着池子里一系列鳄鱼的大脑袋跳上岸去!(据说当年替身演员被最后一条鳄鱼咬住了脚,幸好穿的是特别加厚的靴子才逃过一劫。)

设鳄鱼池是长宽为100米的方形,中心坐标为 (0, 0),且东北角坐标为 (50, 50)。池心岛是以 (0, 0) 为圆心、直径15米的圆。给定池中分布的鳄鱼的坐标、以及007一次能跳跃的最大距离,你需要告诉他是否有可能逃出生天。

输入格式:

首先第一行给出两个正整数:鳄鱼数量 N(≤100)和007一次能跳跃的最大距离 D。随后 N 行,每行给出一条鳄鱼的 (x,y) 坐标。注意:不会有两条鳄鱼待在同一个点上。

输出格式:

如果007有可能逃脱,就在一行中输出"Yes",否则输出"No"。

(MOOC截图)

解题思路:鳄鱼的头可以视为图的顶点,岸边也是图的顶点(在函数中另外讨论),用深度遍历的方法沿着鳄鱼头遍历,直到找到可以跳出去的鳄鱼。

1.输入:首先用一个结构体数组输入数据,index标记是第几个鳄鱼(图的顶点),方便后续建图。因为007被放在圆形小岛上,所以另外还要求出他离每个顶点最近的距离。

2.建图:如果两个顶点的距离<=d,可以跳过去,则两顶点之间存在一条边。

3.从007离顶点最近的点出发,开始找,初始化s=0,是为了在函数中过第四个测试点,即他离所有的顶点的距离都>d。

4.在函数中采用深度优先遍历,判断当前结点离岸边的距离是否小于d,如果s=0,说明所有顶点都够不着就直接返回。

#include<stdio.h>
#include<math.h>
#define MAXN 200
struct node {
	int x, y;
	int index;//顶点编号
	double d1;//和岛的距离
};
int visited[MAXN] = {0};
int edge[MAXN][MAXN] = {0};
int flag = 0;
void DFSEscape(int edge[][MAXN],struct node G[], int n,int d, int s);
int main() {
	int n, d;
	scanf("%d %d", &n, &d);
	int i;
	struct node G[MAXN];
	for (i = 1; i<=n; i++) {
		scanf("%d %d", &G[i].x, &G[i].y);
		G[i].index = i;
		G[i].d1 = pow(G[i].x , 2) + pow(G[i].y, 2);//007离此顶点最近的距离
		G[i].d1 = sqrt(G[i].d1);
		G[i].d1 = G[i].d1 - 15;//第四个测试点存在可能够不着的情况
	}
	double d2;//边长
	for (i = 1; i <= n; i++) {//建图
		for (int j = 1; j <= n; j++) {
			if (sqrt(pow(G[i].x - G[j].x, 2) + pow(G[i].y - G[j].y, 2)) <= d) {
				edge[G[i].index][G[j].index] = 1;
				edge[G[j].index][G[i].index] = 1;
			}
		}
	}
	int  lowcost=123456;
	int s=0;//从s开始
	for (i = 1; i <= n; i++) {//找最近的鳄鱼
		if (lowcost > G[i].d1&&G[i].d1 <=15) {
			lowcost = G[i].d1;
			s = i;
		}
	}
	DFSEscape(edge, G, n, d, s);
	if (flag == 0) {
		printf("No");
	}
	else printf("Yes");
	return 0;
}
void DFSEscape(int edge[][MAXN],struct node G[], int n,int d, int s) {
	if (s == 0)return ;//第四个测试点
	int i;
	visited[s] = 1;
	if (fabs(fabs(G[s].x) - 50) <= d|| fabs(fabs(G[s].y ) - 50) <= d) {//可以到岸
		flag = 1;
		return;
	}
	for (i = 1; i <= n; i++) {//遍历跳跃
		if (edge[s][i] == 1 && visited[i] == 0) {
			DFSEscape(edge, G, n, d, i);
		}
	}
}

根据测试点进行调试,不足之处欢迎指正 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值