知识点:深度优先搜索
评测又卡了,但是udebug上面的数据过了,就先来写一下题解,这种类型的题目之前做过两个了,所以知道这种题目怎么做,其实就是连通性的判断,题目问有没有解,将问题转换为判断障碍物是不是从上到下连通的,这里不只是问有没有解,还要我们求出有解的时候,从左到右,最高的入口和出口的坐标,所以为了统一写法,我们深搜的时候,只有障碍物和上边相连的时候才去搜,因为第一,它可以判断有没有解,第二,它如果和左边想连的话,那么入口的最大值就是它和左边想连的较低的那个坐标,这样就可以求入口的左边,同理可以求出口的坐标,这样一个深搜函数就搞定了有解判定和求解的问题,
写了快20分钟才过了这个题
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
struct node {
double x, y, r;
} a[N];
int n, vis[N];
double ans1, ans2;
bool flag;
double calc(double x) {
return x * x;
}
void dfs(int x) {
vis[x] = 1;
if (a[x].x - a[x].r <= 0) flag = false;
if (a[x].y - a[x].r <= 0) ans1 = min(ans1, a[x].x - sqrt(calc(a[x].r) - calc(a[x].y)));
if (a[x].y + a[x].r >= 1000) ans2 = min(ans2, a[x].x - sqrt(calc(a[x].r) - calc(1000 - a[x].y)));
for (int i = 0; i < n; i++) {
if (!vis[i] && calc(a[x].x - a[i].x) + calc(a[x].y - a[i].y) <= calc(a[x].r + a[i].r)) dfs(i);
}
}
int main() {
while (cin >> n) {
for (int i = 0; i < n; i++) {
cin >> a[i].y >> a[i].x >> a[i].r;
}
memset(vis, 0, sizeof(vis));
ans1 = ans2 = 1000;
flag = true;
for (int i = 0; i < n; i++) {
if (!vis[i] && a[i].x + a[i].r >= 1000) {
dfs(i);
}
}
if (!flag) cout << "IMPOSSIBLE\n";
else printf("0.00 %.2f 1000.00 %.2f\n", ans1, ans2);
}
return 0;
}