在老电影“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);
}
}
}
根据测试点进行调试,不足之处欢迎指正