展开
题目描述
一个秘密组织正在沙漠中举行一次军事演习。本次演习的目标是拆除隐藏在沙漠中的一个炸弹。
演习的第一部分是空降作战。每个士兵按照一定的顺序从悬停在沙漠上空的直升机上跳下。着陆时,每个士兵都会停在他所在的着陆点。
每个空降兵都有一个生存半径。如果炸弹与他的距离小于或等于这个生存半径的话,空降兵便会牺牲自己引爆炸弹。指挥官希望能派出尽可能少的士兵,但他希望在最坏情况下至少有一个士兵能够生还。
整个沙漠可以抽象为一个平面,每个士兵的着陆点可以用一个坐标 (x,y)(x,y) 表示,他的生存半径我们设为 rr。所有士兵的信息按照他们跳伞时的顺序给出,即第 ii 个士兵跳伞时,前 i-1i−1 个士兵都已经着陆。
你的任务是:从标准输入读入所有士兵的信息,输出最少需要派出的士兵数量。
输入格式
第一行一个整数 nn。
接下来 nn 行,第 ii 行包含三个整数 x_i,y_i,r_ixi,yi,ri,代表第 ii 个士兵的着陆坐标为 (x_i,y_i)(xi,yi),生存半径为 r_iri。
输出格式
如果无法让至少一个士兵生还的话,输出 NIE
。
否则输出一个整数,代表至少需要派出的士兵数量。
输入输出样例
输入 #1复制
5 2 2 4 7 2 3 4 3 1 5 7 1 8 7 1
输出 #1复制
4
说明/提示
最坏情况下炸弹位于 (5,3)(5,3),前三个士兵都会被炸死,第四个士兵会生还。
上代码:
#include<bits/stdc++.h>
using namespace std;
#define reg register
typedef long long ll;
const double eps=1e-6;
inline int sgn(reg double x){
if(fabs(x)<eps)
return 0;
else
return x<0?-1:1;
}
inline double sqr(reg double x){
return x*x;
}
const int MAXN=2e3+5;
struct Vector{
double x,y;
inline Vector(reg double x=0,reg double y=0):x(x),y(y){
return;
}
inline Vector operator+(const Vector& a)const{
return Vector(x+a.x,y+a.y);
}
inline Vector operator-(const Vector& a)const{
return Vector(x-a.x,y-a.y);
}
inline Vector operator*(const double a)const{
return Vector(x*a,y*a);
}
};
inline double dot(const Vector& a,const Vector& b){
return a.x*b.x+a.y*b.y;
}
inline double cross(const Vector& a,const Vector& b){
return a.x*b.y-a.y*b.x;
}
typedef Vector Point;
inline double getDis2(const Point& a,const Point& b){
return dot(a-b,a-b);
}
inline double getDis(const Point& a,const Point& b){
return sqrt(getDis2(a,b));
}
inline bool isEmpty(const Point& a){
return a.x!=a.x||a.y!=a.y;
}
struct Circle{
Point o;
double r;
inline bool contain(const Point& x)const{
return sgn(sqr(r)-getDis2(x,o))>=0;
}
inline Point getRig(void)const{
return o+Vector(r,0);
}
};
inline bool isCon(const Circle& a,const Circle& b){
return sgn(sqr(a.r-b.r)-getDis2(a.o,b.o))>=0;
}
inline bool isSep(const Circle& a,const Circle& b){
return sgn(getDis2(a.o,b.o)-sqr(a.r+b.r))>0;
}
inline Point getPot(const Circle &a,const Circle &b){
if(isCon(a,b))
if(sgn(b.getRig().x-a.getRig().x)>0)
return a.getRig();
else
return b.getRig();
else if(isSep(a,b))
return Point(nan(""),nan(""));
else{
if(a.contain(b.getRig()))
return b.getRig();
else if(b.contain(a.getRig()))
return a.getRig();
else{
reg double d=getDis(a.o,b.o);
reg double ang=acos(((sqr(a.r)+sqr(d))-sqr(b.r))/(2*a.r*d));
reg double delta=atan2(b.o.y-a.o.y,b.o.x-a.o.x);
reg double ang1=delta+ang,ang2=delta-ang;
Point p1=a.o+Vector(cos(ang1)*a.r,sin(ang1)*a.r);
Point p2=a.o+Vector(cos(ang2)*a.r,sin(ang2)*a.r);
Point res;
if(sgn(p2.x-p1.x)>0)
res=p2;
else
res=p1;
return res;
}
}
}
int n;
Circle a[MAXN];
int main(void){
scanf("%d",&n);
Point lef(0,0);
for(reg int i=1;i<=n;++i){
static int x,y,r;
scanf("%d%d%d",&x,&y,&r);
a[i].o=Point(x,y),a[i].r=r;
if(i==2)
lef=getPot(a[1],a[2]);
else if(i>2){
for(reg int j=1;j<i&&!isEmpty(lef);++j){
Point tmp=getPot(a[i],a[j]);
if(isEmpty(tmp)||tmp.x<=lef.x)
lef=tmp;
}
for(reg int j=1;j<=i&&!isEmpty(lef);++j)
if(!a[j].contain(lef))
lef=Point(nan(""),nan(""));
}
if(isEmpty(lef)){
printf("%d\n",i);
return 0;
}
}
puts("NIE");
return 0;
}