https://vjudge.net/problem/UVA-11853
题目
一堆人玩水弹(也许是吧),知道他们的坐标和攻击范围,问你从西边到东边能否不被水弹砸。找出西边进入的位置和东边出去的位置。
$n\leqslant1000$
题解
最近一直在写水题……为了看看每道题使用的时间,还写了个计时器,但是这题用的时间太长了……
WA了一次,计算上罚时就是2小时了= =
坐标没看清楚,样例都纠结了半小时,然后少考虑了一种情况
按照紫书上的题解:
看有没有一条把这块地分成左右两边的路……
如果有就无解,没有就有解
然后从北边开始便利,找到与左右边界相交的最南边的坐标
AC代码
#include<bits/stdc++.h>
using namespace std;
#define REP(i,x,y) for(register int i=(x); i<(y); i++)
#define REPE(i,x,y) for(register int i=(x); i<=(y); i++)
#ifdef sahdsg
#define DBG(a,...) printf(a, ##__VA_ARGS__)
#else
#define DBG(a,...) (void)0
#endif
#define MAXN 1007
int n;
struct yuan {
double r,x,y;
} arr[MAXN];
inline bool conn(int i, int j) {
double rr = arr[i].r+arr[j].r;
double dx = arr[i].x-arr[j].x;
double dy = arr[i].y-arr[j].y;
rr*=rr;
dx*=dx;
dy*=dy;
return dx+dy<=rr;
}
bool vis[MAXN];
inline bool bfs1(int i) {
queue<int> q;
q.push(i);
vis[i]=true;
while(!q.empty()) {
int now = q.front(); q.pop();
if(arr[now].y-arr[now].r<=0) return true;
REP(i,0,n) {
if(!vis[i] && conn(now,i)) {
q.push(i);
vis[i]=true;
}
}
}
return false;
}
double ans1, ans2;
bool has1, has2;
inline void bfs2(int i) {
queue<int> q;
q.push(i);
while(!q.empty()) {
int now = q.front(); q.pop();
if(arr[now].x-arr[now].r<=0) {
ans1=min(ans1,arr[now].y-sqrt(arr[now].r*arr[now].r-arr[now].x*arr[now].x));
}
if(arr[now].x+arr[now].r>=1000) {
double dx=1000.0-arr[now].x;
ans2=min(ans2,arr[now].y-sqrt(arr[now].r*arr[now].r-dx*dx));
}
REP(i,0,n) {
if(!vis[i] && conn(now,i)) {
q.push(i);
vis[i]=true;
}
}
}
}
int main() {
#ifdef sahdsg
freopen("in.txt","r",stdin);
#endif
while(~scanf("%d", &n)) {
REP(i,0,n) {
double &x=arr[i].x, &y=arr[i].y, &r=arr[i].r;
scanf("%lf%lf%lf", &x, &y, &r);
}
bool f=true;
memset(vis,0,sizeof vis);
REP(i,0,n) {
double &x=arr[i].x, &y=arr[i].y, &r=arr[i].r;
if(!vis[i] && y+r>=1000) {
if(bfs1(i)) {
f=false;
break;
}
}
}
if(!f) {
puts("IMPOSSIBLE");
} else {
memset(vis,0,sizeof vis);
ans1=ans2=1000;
has1=has2=false;
REP(i,0,n) {
double &x=arr[i].x, &y=arr[i].y, &r=arr[i].r;
if(!vis[i] && y+r>=1000) {
bfs2(i);
}
}
printf("0.00 %.2lf 1000.00 %.2lf\n", ans1, ans2);
}
}
return 0;
}