POJ 1328--Radar Installation

来源:互联网 发布:怎么统计淘宝分类消费 编辑:程序博客网 时间:2024/06/06 00:53

2017-10-02
原题链接

题目大意:在一个x-y坐标系中,x轴上方给出若干个点,可以在x轴上作若干个半径为d的圆以覆盖所有的点。求圆的最少个数。

样例输入(若干组,每组第一行两个数表示点的个数和圆的半径,以“0 0”组表示输入结束):

3 21 2-3 12 11 20 20 0

样例输出:

Case 1: 2Case 2: 1

本题的思路是根据给定的点的坐标和半径求出对于每个点,圆心在x轴上的可能范围,再将所有圆心范围排序,去掉重叠区域求得最少的圆的个数。
个人在做这题时出现了各种各样的错误……简直把所有可能的错误都经历了一遍。。总之,以下两点个人认为特别值得注意:
1.即使一组输入中已经出现了使得这组输入无解的数据,也必须接收完这组输入,否则会出现Runtime Error;
2.本题中将范围排序时,必须根据范围的右边界进行比较,根据左边界比较将出错。比如:在一个很大范围里包含着N个相互没有交集的小范围的情况下,按左边界排序会得出需要一个圆(错),而按右边界排序会求出需要N-1个圆。

参考题解

代码:

#include <cstdio>#include <algorithm>#include <cmath>using namespace std;struct node {    double Start,End;  //Start:左边界,End:右边界};bool cmp(node a, node b) {    return a.End < b.End;       //* 此处一定是比较End,比较Start则Wrong Answer *}node radar[1010];       //雷达坐标范围int Num = 1;            //样例编号int main() {    int n;    double d;    while(scanf("%d%lf",&n,&d),n||d) {        bool isAns = true; //是否有解        double x,y;        for(int i = 0; i < n; i++) {            scanf("%lf%lf",&x,&y);            if(!isAns) continue;    //* 此处千万不能break,否则会runtime error *            if(y > d) {                isAns = false;                continue;            }            radar[i].Start = x - sqrt(d*d - y*y);            radar[i].End = x + sqrt(d*d - y*y);     //雷达坐标区间        }        printf("Case %d: ",Num++);        if(!isAns) {            printf("-1\n");            continue;        }        int ans = 0;        double right = -100000000;        sort(radar,radar+n,cmp);        for(int i = 0; i < n; i++) {            if(radar[i].Start > right) {                ans++;                right = radar[i].End;            }        }        printf("%d\n",ans);    }    return 0;}
原创粉丝点击