題目詳情:
在老電影“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
題目思路:
這道題目的解題中使用到了dfs和圖的相關知識,
p[]是所輸入的每個節點的數組(鱷魚的集合)
vis[]是判斷是否該節點被訪問:
如果被訪問過了,那麼只有兩種情況:1.找到出口,直接彈出(break)。2.沒有出口~
所以如果節點被訪問過,就意味着該節點不是出口。
另外注意我們還有對於第一次的中心島的特殊判斷,他的距離與其他的dfs過程不同。
#include<bits/stdc++.h>
using namespace std;
int n,d;
struct node//定義節點(存儲x,y座標)
{
int x;
int y;
}p[110];
bool vis[110];
bool flag =0;
bool first(int i){//判斷該節點是否可以在第一次可以跳出中心島(即判斷該點是否在第一次跳出的半徑內)
return(p[i].x*p[i].x+p[i].y*p[i].y <= (d+7.5)*(d+7.5));
}
bool success(int i){//判斷能否在該結點處一次直接跳出(d>0),分別判斷x,y是否可以跳出邊界(即能否一步上岸)
return p[i].x-d<=-50||p[i].x+d>=50||p[i].y+d>=50||p[i].y-d<=-50;
}
bool isJump(int i,int j){//判斷是否可以從一點跳到另一點
return (p[i].x*p[i].x+p[i].y*p[i].y)<d*d;
}
int dfs(int i){//遞歸,dfs判斷是否可以找到出去的路
vis[i] = 1;//表示已經訪問該節點
if(success(i))return 1;
for(int j=0;j<n;j++){//遍歷尋找節點
if(!vis[j]&&isJump(i,j))
{//如果該點訪問過,那麼此路就代表不通,應該放棄這個點;同時我們還要找到可以跳躍過去的點。
if(dfs(j))return 1;
}
}
return false;
}
int main(){
cin>>n>>d;
for(int i=0;i<n;i++){
cin>>p[i].x>>p[i].y;
}
if(d>=42.5)flag = true;
else {
for(int i=0;i<n;i++){//應該通過遍歷找到符合條件的節點
if(!vis[i]&&first(i))//如果沒有訪問過這個節點,且在第一次跳出的半徑內。
if(dfs(i)){
flag =1;
break;//跳出並不再尋找
}
}
}
if(flag)cout<<"yes";
else cout<<"no";
}