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++ ,