PTA 7-11 拯救007 基础dfs

在老电影“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"。
输入样例 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

输出样例 1:

Yes

输入样例 2:

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

输出样例 2:

No

作者
陈越
单位
浙江大学
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB

题意如图 :
在这里插入图片描述
把所有靠近岛屿的点为起点dfs即可,当dfs到某个点point[i],能跳出去的条件是
x+D>=50 || x-D<=-50 || y+D>=50 || y-D<=-50,即越出边界
预处理point[i]和point[j]两两点之间的距离mtx[i][j]

代码如下

#define debug
#ifdef debug
#include <time.h>
#include "/home/majiao/mb.h"
#endif

#include <iostream>
#include <algorithm>
#include <vector>
#include <string.h>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <math.h>

#define MAXN (256)
#define ll long long 
#define INF (0x7f7f7f7f)
#define fori(lef, rig) for(int i=lef; i<=rig; i++)
#define forj(lef, rig) for(int j=lef; j<=rig; j++)
#define fork(lef, rig) for(int k=lef; k<=rig; k++)
#define QAQ (0)

using namespace std;

#ifdef debug
#define show(x...)                                 \
	do {                                           \
		cout << "\033[31;1m " << #x << " -> ";     \
		err(x);                                    \
	} while (0) 
#else
#define show(x...)  
#endif

void err() { cout << "\033[39;0m" << endl; }
template<typename T, typename... A>
void err(T a, A... x) { cout << a << ' '; err(x...); }

namespace FastIO {

	char print_f[105];
	void read() { }
	void print() { putchar('\n'); }

	template <typename T, typename... T2>
		inline void read(T &x, T2 &... oth) {
			x = 0;
			char ch = getchar();
			ll f = 1;
			while (!isdigit(ch)) {
				if (ch == '-') f *= -1; 
				ch = getchar();
			}
			while (isdigit(ch)) {
				x = x * 10 + ch - 48;
				ch = getchar();
			}
			x *= f;
			read(oth...);
		}
	template <typename T>
		inline void put(T x) {
			if(x==0) { putchar('0'); putchar('\n'); return; }
			if(x<0) { putchar('-'); x = -x; }
			int num=0;
			char ch[128];
			while(x) ch[++num] = x % 10 + '0', x /= 10;
			while(num) putchar(ch[num--]);
			putchar('\n');
		}
}; // namespace FastIO
using FastIO::read;
using FastIO::put;

int n, m, Q, K;

struct Node {
	double x, y;
} a[MAXN];

double mtx[MAXN][MAXN];

inline double dist(double x1, double x2, double y1, double y2) {
	double X = x1 - x2, Y = y1 - y2;
	return sqrt(X*X + Y*Y);
}

bool canout = false, vis[MAXN];

//判断当前坐标(x,y)是否可以跳出去
#define OUT(x, y) ((x+m>=50) || (x-m)<=-50 || ((y+m>=50) || (y-m)<=-50))

void dfs(int u) {
	vis[u] = true;
	if(canout) return ;
	if(OUT(a[u].x, a[u].y)) {
		canout = true;
		return ;
	}
	for(int i=1; i<=n; i++) {
		if(vis[i]) continue ;
		if(mtx[u][i] <= m) dfs(i); //只跳到够得着的点
	}
}

signed main() {
#ifdef debug
	freopen("test", "r", stdin);
	// freopen("out_main", "w", stdout);
	clock_t stime = clock();
#endif
	scanf("%d %d ", &n, &m);
	vector<int> start; //所有起点
	for(int i=1; i<=n; i++) { //预处理所有起点
		scanf("%lf %lf ", &a[i].x, &a[i].y);
		double td = dist(0, a[i].x, 0, a[i].y);
		if(td <= 7.5+m) start.push_back(i);
#if 0
		if(dist(0, 0, a[i].x, a[i].y) <= 7.5+m) {
			show(dist(0, a[i].x, 0, a[i].y), a[i].x, a[i].y);
			start.push_back(i);
		}
#endif
	}
	for(int i=1; i<=n; i++) //预处理任意两点间的距离
		for(int j=1; j<=n; j++) {
			mtx[i][j] = dist(a[i].x, a[j].x, a[i].y, a[j].y);
		}
	for(int i=0; i<int(start.size()) && !canout; i++) { //枚举起点dfs即可
		memset(vis, false, sizeof(vis));
		dfs(start[i]);
	}
	printf("%s\n", canout ? "Yes" : "No");















#ifdef debug
	clock_t etime = clock();
	printf("rum time: %lf 秒\n",(double) (etime-stime)/CLOCKS_PER_SEC);
#endif 
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值