给出若干个圆,用弧度给出起点和终点,问是否能够在太空船的范围内找到一条路径,从起点到终点。
判断两圆相交,建图,分成两个区间。
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
using namespace std;
const int maxn=1000+10; //最大陨石数
const double eps=1e-8; //控制精度
const double pi=acos(-1.0);
double d1,d2,R;
double xd1,xd2,yd1,yd2;
int n;
double x[maxn],y[maxn],r[maxn];
int a[maxn][maxn];
int b[maxn];
int cas;
inline double dis(double x,double y)
{
return sqrt(x*x+y*y);
}
inline double helen(double a,double b,double c)
{
double p=(a+b+c)/2.0;
return sqrt(p*(p-a)*(p-b)*(p-c));
}
int intersect(int i,int j)//利用面积判断两个圆的交点是否在另一个圆内
{
double di=dis(x[i],y[i]);
double dj=dis(x[j],y[j]);
double ij=dis(x[i]-x[j],y[i]-y[j]);
double S=helen(di,dj,ij);
double Si=helen(di,r[i],R);
double Sj=helen(dj,r[j],R);
double Sij=helen(ij,r[i],r[j]);
return Si+Sj+Sij>S;
}
int dfs(int root)
{
if(b[root]==2)return 0;
b[root]=0;//标记已经访问过
int i;
for(i=0;i<n;i++)
if(b[i]&&a[root][i]==cas)
{
if(dfs(i)==0)return 0;//如果没访问过则进行访问
}
return 1;
}
int main()
{
int T;
scanf("%d",&T);
double tmp,d,di;
int ok;
int i,j;
memset(a,0,sizeof(a));
cas=0;
while(T--)
{
cas++;
scanf("%lf%lf%lf",&R,&d1,&d2);
if(d1>d2)
{
tmp=d1;
d1=d2;
d2=tmp;
}
d1=pi/180.0*d1;
d2=pi/180.0*d2;
xd1=R*cos(d1);
yd1=R*sin(d1);
xd2=R*cos(d2);
yd2=R*sin(d2);
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%lf%lf%lf",&x[i],&y[i],&r[i]);
ok=1;
memset(b,0,sizeof(b));
for(i=0;i<n;i++)
{
d=dis(x[i],y[i]);
if(d>R+r[i]+eps)
{
b[i]=0;
continue;
}
if(r[i]+d+eps<R)
{
b[i]=3;
continue;
}
if(dis(x[i]-xd1,y[i]-yd1)<=eps+r[i]||dis(x[i]-xd2,y[i]-yd2)<=eps+r[i])
{
ok=0;
continue;
}
di=acos(x[i]/d);
if(y[i]<0.0)di=pi+pi-di;
if(di>d1&&di<d2)b[i]=1;
else b[i]=2;
}
if(!ok)
{
printf("Die hard!\n");
continue;
}
for(i=0;i<n;i++)
if(b[i])
for(j=i+1;j<n;j++)
if(b[j])
if(dis(x[i]-x[j],y[i]-y[j])<=r[i]+r[j])
{
if(b[i]+b[j]!=3||intersect(i,j))
a[i][j]=a[j][i]=cas;
}
for(i=0;i<n;i++)
{
if(b[i]==1)
ok=dfs(i);
if(!ok)break;
}
if(ok)printf("Escape!\n");
else printf("Die hard!\n");
}
return 0;
}
from sysu.