题目链接:https://vjudge.net/contest/397282#problem/A
题解:
判断一个人能否从左下到达右上是判断所围成的图形能否围住他,而所构成的图形有C2 4=6种情况,
现在是判断能否从左边界或者上边界到达右边界或者下边界。
算法是储存左上角的点,逐个判断与他相邻的点,如果能够到达右下角,那么该人到达不了右上角,注意每次路径都需要重置。
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
struct p
{
int rr;//横坐标
int cc;//纵坐标
int ra;//半径
};
int rc[1100];//储存横坐标
p P[1100];//储存点
int r,c;//代表长和宽
int n;//点的个数
int fl,fl2;//判断横纵坐标是否到边界
int f[1100];//标记是否被用过
int cou=0;//储存个数
void dfs(int i)//序数
{
if(fl2==1)//判断是否能从左下角到达右上角
return ;
if(P[i].cc<=P[i].ra||P[i].ra+P[i].rr>=r)
{
fl2=1;
return ;
}
for(int j=0; j<n; j++)
{
if(f[j]==0)//没用过
{
if((P[i].rr-P[j].rr)*(P[i].rr-P[j].rr)+(P[i].cc-P[j].cc)*(P[i].cc-P[j].cc)<=(P[i].ra+P[j].ra)*(P[i].ra+P[j].ra))
//距离小于等于圆心之间的距离
{
f[j]=1;
dfs(j);
f[j]=0;
}
}
}
return;
}
int main()
{
memset(f,0,sizeof(f));
scanf("%d%d",&r,&c);
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%d%d%d",&P[i].rr,&P[i].cc,&P[i].ra);
if(P[i].rr<=P[i].ra||P[i].cc+P[i].ra>=c)
{
cou++;
rc[cou]=i;//储存右上角
}
if(P[i].cc<=P[i].ra||P[i].ra+P[i].rr>=r)
fl=1;//储存左下角
}
if(fl==1&&cou>=1)
{
for(int i=1; i<=cou; i++)//多个左下角的点逐次判断
{
f[rc[i]]=1;
dfs(rc[i]);
f[rc[i]]=0;
}
if(fl2==1)
printf("N");
else
printf("S");
}
else
printf("S");
return 0;
}