题目大意:
以x轴为分界,y>0部分为海,y<0部分为陆地,给出一些岛屿坐标(在海中),再给出雷达可达到范围,雷达只可以安在陆地上,问最少多少雷达可以覆盖所以岛屿。
解题思路:
以岛屿为圆心r为半径画一个圆(记为圆O),于是只要雷达在这个圆里那么这个岛屿就能被覆盖。而从前面的分析可知,雷达必然要布置在x轴上,所以雷达肯定放在圆O与x轴的那段交线区间上
所以我们可以将所有的岛屿对应的这段区间记录下来,然后以区间左界从小到大排序就行,之后从第一个区间开始,如果第二个区间与其有交集,就更新这个交集,并从队列中除去区间1,2,如果第三个区间与这个交集又有交集,那么便更新交集并除去区间3直到不满足有交集为止。然后继续模拟这个过程就行了,每模拟以此这个过程ANS++(即区间选点问题)
#include <cstdio> //此题样例过了,但是依然没能AC,主要是我对这道题的公认的解题思路仍然有一些质疑 #include <cmath> #include <algorithm> using namespace std; int n,ans=0,res; double d; struct node { double x, y; }; struct region { double x1, x2; }; bool cmp(region a, region b) { return a.x1 < b.x1; } int main() { int i, j; while (scanf("%d%lf", &n, &d) != EOF,n||d) { node nod[1100]; region reg[1100]; ans++; if (d <0) { printf("-1\n"); return 0; } for (i = 0; i < n; i++) { scanf("%lf%lf", &nod[i].x, &nod[i].y); if (nod[i].y > d||nod[i].y<=0) { printf("-1\n"); return 0; } } for (i = 0; i < n; i++) { reg[i].x1 = nod[i].x - sqrt(d*d*1.0 - nod[i].y*nod[i].y*1.0); reg[i].x2 = nod[i].x + sqrt(d*d*1.0 - nod[i].y*nod[i].y*1.0); } sort(reg, reg + n, cmp); //为什么按区间左值从小到大排序合并就是最优,我认为要区间中心距离最近的点优先合并才是最优 res = 1; double end = reg[0].x2; for (i = 1; i < n; i++) { if (reg[i].x1 > end) { res++; end = reg[i].x2; } else if (reg[i].x1 <= end && reg[i].x2 <= end) { end = reg[i].x2; } } printf("Case %d: %d\n", ans, res); } return 0; }
2018-04-01