链接:点击打开链接
题意:作为H国的精英特工,你接到了一项任务,驾驶一辆吉普穿越布满监测雷达的禁区。为了简化题目,我们可以把禁区想象为一个左下角是(0, 0)右上角是( W, H )的长方形区域。区域中一共有 N 座雷达,其中第 i 座的坐标是(Xi, Yi ),监测范围是半径为 Ri 的圆形区域。所有在圆内和圆上的运载工具都会被监测到。
你的目标是从左到右穿越禁区。你可以选择线段(0, 0)-(0, H)上任意一点作为起点,线段(W, 0)-(W, H)上任意一点作为终点。在禁区内你可以沿任意路线行驶,只要保持始终在禁区内并且没有被雷达监测到。
给出禁区内的雷达部署方案,你需要判断是否存在满足条件的行驶路线。
代码:
#include <set>
#include <queue>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct node{
long long x,y,r;
}s[1005];
int judge(node a,node b){
long long l1,l2;
l1=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
l2=(a.r+b.r)*(a.r+b.r);
if(l1<=l2)
return 1;
return 0;
}
long long fa[1005];
long long get(long long x){
if(x==fa[x])
return x;
return fa[x]=get(fa[x]);
}
void unite(long long x,long long y){
x=get(x);
y=get(y);
if(x==y)
return;
fa[x]=y;
}
long long same(long long x,long long y){
return get(x)==get(y);
}
int main(){ //把上下边界和每个圆都各看成一个点,
long long w,h,n,i,j,t,op; //两两相交就用并查集维护,看最后上下
scanf("%lld",&t); //边界点是否在一个集合
while(t--){ //还可以连成图dfs判断
scanf("%lld%lld%lld",&w,&h,&n);
for(i=0;i<=n+1;i++)
fa[i]=i;
for(i=1;i<=n;i++){
scanf("%lld%lld%lld",&s[i].x,&s[i].y,&s[i].r);
if(s[i].y-s[i].r<=0)
unite(i,0);
if(s[i].y+s[i].r>=h)
unite(i,n+1);
}
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
if(i==j)
continue;
if(judge(s[i],s[j]))
unite(i,j);
}
}
if(same(0,n+1))
puts("NO");
else
puts("YES");
}
return 0;
}