UVA

来源:互联网 发布:电视频道直播软件 编辑:程序博客网 时间:2024/06/16 05:26

题目链接

题意

如果大家是从lrj的书中例题看到本题,相信对题意不会太陌生,所以就不重复说了

解题思路

书中lrj也讲了思路,代码也可以下载,这篇博客就是说明一下为什么入口和出口的求法的正确性。

样例中敌人分布

从图片中可以看到样例有解。建议大家先阅读了代码中求法及在什么条件下调用该函数。看了后发现是在dfs中调检查该圆是否与左边相交,如果相交说明从该圆与左边的下交点到(0,1000)都不能作为入口;如下图所示

没有延伸的情况

图中与该条路径已经没有延伸,调用check_circle(),求得点left既为入口最靠北的点;ps:我对与题目中所说的严格大于敌人攻击范围的条件,但所求的确是等于的情况有点疑惑。

有延伸的情况

如上图是有延伸的情况,但是依然满足上面所说的最小交点(y值最小)便是满足题意的入口。求出口的原理与入口相同。

代码

// UVa11853 Paintball// Rujia Liu#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>using namespace std;const int maxn = 1000 + 5;const double W = 1000.0;int n, vis[maxn];double x[maxn], y[maxn], r[maxn], left, right;bool ok;bool intersect(int c1, int c2){    return sqrt((x[c1]-x[c2])*(x[c1]-x[c2]) + (y[c1]-y[c2])*(y[c1]-y[c2])) < r[c1] + r[c2];}void check_circle(int u){    if(x[u] - r[u] < 0)        left = min(left, y[u] - sqrt(r[u]*r[u] - x[u]*x[u]));    if(x[u] + r[u] > W)        right = min(right, y[u] - sqrt(r[u]*r[u] - (W-x[u])*(W-x[u])));}// 能达到底部则返回truebool dfs(int u){    if(vis[u]) return false;    vis[u] = 1;    if(y[u] - r[u] < 0) return true;    for(int v = 0; v < n; v++)        if(intersect(u, v) && dfs(v)) return true;    check_circle(u);    return false;}int main(){    while(scanf("%d", &n) == 1)    {        ok = true;        left = right = W;        memset(vis, 0, sizeof(vis));        for(int i = 0; i < n; i++)            scanf("%lf%lf%lf", &x[i], &y[i], &r[i]);        for(int i = 0; i < n; i++)            if(y[i] + r[i] >= W && dfs(i))            {                ok = false;    // 从上往下dfs                break;            }        if(ok) printf("0.00 %.2lf %.2lf %.2lf\n", left, W, right);        else printf("IMPOSSIBLE\n");    }    return 0;}
原创粉丝点击