题目背景就是Unix下的同名游戏..
每个机器人每秒钟向你移动,移动方式是,假设你为原点,则他会沿着一条斜率为±1的直线靠近你,直到它移动到了某个坐标轴上,然后就沿着坐标轴靠近你。每秒钟每个坐标的变化量都最多是1。
如果两个机器人撞在了一起,即出现在了同一个坐标中,那么他们就会消失并产生一个黑洞。题目开始也会有一些黑洞。如果机器人移动到了黑洞上,则机器人也会消失。黑洞一旦出现就永远不会消失。
问你呆在一个位置不动,已知机器人的初始位置,他们同时开始向你移动,问能否有机器人最终移动到你的坐标?
如果机器人在你所在的位置上碰撞,是不算的。认为他们能够移动到你的坐标。
暴力枚举所有机器人和所有机器人的碰撞时间,以及所有机器人和所有黑洞的碰撞时间。复杂度10^6。
#include <cstdio>
#include <set>
#include <utility>
using namespace std;
const int INF=~0u>>1;
inline int sgn(int x) {
if (x>0) return 1;
if (x<0) return -1;
return 0;
}
inline int abs(int x) {
return x>0?x:-x;
}
inline int max(int a,int b) {
return a>b?a:b;
}
inline int min(int a,int b) {
return a<b?a:b;
}
struct Bomb {
set<pair<int,int> >::iterator a,b;
bool isBRobot;
int t,x,y;
Bomb(int tt) {
t=tt;
}
Bomb(set<pair<int,int> >::iterator aa,set<pair<int,int> >::iterator bb,bool br) {
isBRobot=br;
a=aa;b=bb;
//calculate bomb time and location
int ax=aa->first,ay=aa->second,bx=bb->first,by=bb->second;
if (isBRobot) {
if (ax==bx) {
if (abs(ay)<abs(ax)&&abs(by)<abs(bx)) {
t=max(abs(ay),abs(by));
if (ax>0) x=ax-t;
else x=ax+t;
y=0;
} else t=INF;
} else if (ay==by) {
if (abs(ay)>abs(ax)&&abs(by)>abs(bx)) {
t=max(abs(ax),abs(bx));
x=0;
if (ay>0) y=ay-t;
else y=ay+t;
} else t=INF;
} else t=INF;
} else {
int tmp=min(abs(ax),abs(ay)),tmpx,tmpy;
if (ax>0) tmpx=ax-tmp;
else tmpx=ax+tmp;
if (ay>0) tmpy=ay-tmp;
else tmpy=ay+tmp;
if ((abs(bx-tmpx)==abs(by-tmpy)&&abs(bx-tmpx)<=abs(ax-tmpx)&&sgn(bx-tmpx)==sgn(ax-tmpx)&&sgn(by-tmpy)==sgn(ay-tmpy))
||(abs(bx)<=abs(tmpx)&&abs(by)<=abs(tmpy)&&sgn(bx)==sgn(tmpx)&&sgn(by)==sgn(tmpy))) {
t=max(abs(ax-bx),abs(ay-by));
} else t=INF;
}
//printf("Constructor: (%d,%d) (%d,%d)%c %d\n",a->first,a->second,b->first,b->second,br?'R':'C',t);
}
friend bool operator <= (const Bomb &a,const Bomb &b) {
return a.t<=b.t;
}
};
set<pair<int,int> >robot;
set<pair<int,int> >hole;
int sx,sy,n,m;
int main() {
int i;
while (scanf("%d%d",&sx,&sy)!=EOF) {
robot.clear();
hole.clear();
scanf("%d",&n);
for (i=0;i<n;i++) {
int x,y;
scanf("%d%d",&x,&y);
robot.insert(make_pair(x-sx,y-sy));
}
scanf("%d",&m);
for (i=0;i<m;i++) {
int x,y;
scanf("%d%d",&x,&y);
hole.insert(make_pair(x-sx,y-sy));
}
bool ans=false;
Bomb lastminBomb=Bomb(0);
while (!robot.empty()) {
Bomb minBomb=Bomb(INF);
/*
printf("New Round: --lastBomb %d\n",lastminBomb.t);
printf("Robot:\n");
for (set<pair<int,int> >::iterator it=robot.begin();it!=robot.end();it++) {
printf(" (%d,%d)\n",it->first,it->second);
}
printf("Hole\n");
for (set<pair<int,int> >::iterator it=hole.begin();it!=hole.end();it++) {
printf(" (%d,%d)\n",it->first,it->second);
}
*/
for (set<pair<int,int> >::iterator it1=robot.begin();it1!=robot.end();it1++) {
set<pair<int,int> >::iterator it2=it1;
it2++;
while (it2!=robot.end()) {
Bomb tmp=Bomb(it1,it2,true);
if (lastminBomb<=tmp&&tmp<=minBomb) minBomb=tmp;
it2++;
}
}
for (set<pair<int,int> >::iterator it1=robot.begin();it1!=robot.end();it1++) {
for (set<pair<int,int> >::iterator it2=hole.begin();it2!=hole.end();it2++) {
Bomb tmp=Bomb(it1,it2,false);
if (lastminBomb<=tmp&&tmp<=minBomb) minBomb=tmp;
}
}
//printf("(%d,%d) (%d,%d) %d\n",minBomb.a->first,minBomb.a->second,minBomb.b->first,minBomb.b->second,minBomb.t);
if (minBomb.t!=INF) {
if (minBomb.isBRobot) {
robot.erase(minBomb.a);
robot.erase(minBomb.b);
hole.insert(make_pair(minBomb.x,minBomb.y));
} else {
robot.erase(minBomb.a);
}
} else {
ans=true;
break;
}
lastminBomb=minBomb;
}
if (ans) printf("NO\n");
else printf("YES\n");
}
return 0;
}