题目在此数组
解题思路:性能
以岛屿坐标为圆心,输入值为半径画圆,此圆会与 X 轴相交于 S、E 两点(岛屿 Y 坐标等于圆半径时,交一点;Y 坐标大于圆半径的状况提早排除,不参与后面的计算)。而后对由 S、E 组成的线段以 E 为断定标准排序,从左至右计算最少雷达个数。优化
吐个槽:POJ 落后于时代了,支持语言少,不支持 C++11 也就罢了,大多数题目时限居然只有 1000ms。这道题我一开始是用 vector、cin/cout 等 C++ 经常使用特性作的,提交后居然超时。无奈用 C 重写——改用 scanf/printf、静态建立数组等等。逻辑没变,再次提交,运行时间减为 16ms(这种状况已是第二次碰到了,看来之后写 POJ 程序时得专门针对题目优化才行了)。让你们重视程序运行性能当然没错,但相信真正写程序的话没人会以静态建立数组的方法把数据的处理规模写死吧?咱们不能为了作题而作题,对吧?code
不啰嗦了,上代码。对象
#include <cstdio> #include <algorithm> #include <cmath> // 岛屿对象 struct coordinate { // 坐标、与 X 轴相交线段的起/终点 double x, y; double s, e; bool operator<(const coordinate &o) const { return e < o.e; } } island[1001]; int solve(int n, int d) { // 计算相交线段起/终点 for (int i = 0; i < n; ++i) { double t = sqrt(d - island[i].y * island[i].y); island[i].s = island[i].x - t; island[i].e = island[i].x + t; } // 依线段终点排序 std::sort(island, island + n); // 最少雷达数量(特殊状况已在输入时排除掉, // 程序执行到这里时,至少存在一个合法岛屿, // 故 ans 初始为 1) int ans = 1; double r = island[0].e; // 从第二座岛屿开始扫描,如前一雷达设置点 // 覆盖不到,则雷达数加 1 for (int i = 1; i < n; ++i) { if (island[i].s > r) { ++ans; r = island[i].e; } } return ans; } int main() { int c = 1; int n, d; while (scanf("%d %d", &n, &d) && (n || d)) { bool np = false; for (int i = 0; i < n; ++i) { // 坐标明明为整数,但用 scanf 时 // 后面计算时会出现精度不够的状况, // 用 cin 则无此问题 -_-!!! scanf("%lf %lf", &island[i].x, &island[i].y); // 若是岛屿坐标超出雷达覆盖范围, // 排除此状况,不参与计算 if (island[i].y > d) { np = true; } } if (np) { printf("Case %d: %d\n", c, -1); } else { // 直接传入半径平方,减小重复计算 printf("Case %d: %d\n", c, solve(n, d * d)); } ++c; } return 0; }