当前位置:编程学习 > C/C++ >>

poj1328

贪心。

一开始的思路:

 

\


图中ABCD为海岛的位置。假设本题半径为2(符合坐标系),那么A点坐标为(1,1)以此类推。

在题中,记录每个点的坐标,并把一个点新加一个标记变量以标记是否被访问过。

首先以A为圆心,r为半径做圆,交x轴与E1(右)点,做出如图中绿色虚线圆。然后以E1为圆心,半径为r做圆。看此时下一点(B)是否在该圆中。如果在,那么将该点标记变量变为true,再判下一点(C),如果不在那么就新增一个雷达。

后来,换了思路,存储图中红色圆与X轴的交点。

还是原来的贪心思路,仍然先排序,但排序的准则是按红色圆与x轴左交点的先后顺序。

如图,如果B点圆(且如此称呼)的左交点(J1点)在A点圆右交点(E1)左侧,那么B点一定涵盖在A点圆内部。再如图,如果D点圆的左交点(图中未标示)在A点圆的右交点(未标示)右,则D点不在A点圆中。

故,有如下代码:

#include <iostream>   
#include <algorithm>   
#include <stdlib.h>   
#include <math.h>   
  
using namespace std;  
  
struct point  
{  
    double left, right;  
}p[2010], temp;  
  
bool operator < (point a, point b)  
{  
    return a.left < b.left;  
}  
  
int main()  
{  
    int n;  
    double r;  
    int kase = 0;  
    while (cin >> n >> r && (n || r))  
    {  
        bool flag = false;  
        for (int i = 0; i < n; i++)  
        {  
            double a, b;  
            cin >> a >> b;  
            if (fabs(b) > r)  
            {  
                flag = true;  
            }  
            else  
            {  
                p[i].left = a * 1.0 - sqrt(r * r - b * b);  
                p[i].right = a * 1.0 + sqrt(r * r - b * b);  
            }  
        }  
        cout << "Case " << ++kase << ": ";  
        if (flag)  
        {  
            cout << -1 << endl;  
        }  
        else  
        {  
            int countt = 1;  
            sort(p, p + n);  
            temp = p[0];  
              
            for (int i = 1; i < n; i++)  
            {  
                if (p[i].left > temp.right)  
                {  
                    countt++;  
                    temp = p[i];  
                }  
                else if (p[i].right < temp.right)  
                {  
                    temp = p[i];  
                }  
            }  
            cout << countt << endl;  
        }  
    }  
}  

 

补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,