Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 71472 | Accepted: 15992 |
Description
Input
Output
Sample Input
3 2 1 2 -3 1 2 1 1 2 0 2 0 0
Sample Output
Case 1: 2 Case 2: 1
此题与第六届河南省省赛的第二题很相似(唯一的区别就是若不能被覆盖则输出-1)省赛无-1 的输出
题意:有一个坐标轴 在X轴上方是海 下方是陆地 X轴是海岸线,海上有N个小岛,现在要在海岸线上安装雷达,
雷达的覆盖范围是一个以R为半径的圆,请用最少的雷达覆盖所有的小岛;当无法覆盖时 输出-1
思路:
算出 每个小岛能被覆盖的雷达的圆心,即以小岛为圆心 R为半径 作圆,该圆与X轴的交点:
左交点为x-sqrt(R*R-y*y); 右交点为x+sqrt(R*R-y*y);(在这个左右焦点区域内的圆心均能将这个小岛给覆盖住)
按照 左交点 排序,如果i点的左交点在 当前雷达的右边 则需安装一个新雷达,更新雷达
否则 如果 i点的右交点也在当前雷达的左边 则把当前雷达的圆心更新为该点的右交点;
(如果按照左区间排序则应选尽量小的区间,如果左右的焦点均在t的左方,则按照尽量小的区间,交换t=小区间的右焦点))(因为是选择尽量少的雷达去覆盖如果在一个区间内部还有更小的区间的话,应选择更小的区间去覆盖(因为若选择在两个区间的左端点距离处放雷达的话,无法覆盖第二个小区间内的岛屿))
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <cmath> using namespace std; struct circle { double l; double r;///因为下面是Sqrt所以定为double }s[1005]; int cmp(circle a,circle b) { return a.l<b.l; ///按照左焦点从小到大排列 } int main() { int n,m; double x,y; ///Sqrt int Case=0; while(scanf("%d %d",&n,&m),(n+m)) { int ans=1; for(int i=0;i<n;i++) { scanf("%lf %lf",&x,&y); s[i].l=x-sqrt(m*m-y*y);///将每个岛雷达的区域 ///映射在水平分线上 s[i].r=x+sqrt(m*m-y*y); if(y<0||m<=0||y>m)///考虑边界(岛的区域不可在陆地上, /// 雷达的半径不可小于零) ans=-1; } sort(s,s+n,cmp); double t=s[0].r; for(int i=1;i<n&&ans!=-1;i++) if(s[i].l>t) { ans++; t=s[i].r; } else if(s[i].r<t)///如果下一个岛屿的左右焦点均在t的左侧 ///则选择小的区间的右焦点(尽量小区间)(若大区间内部有小区间(选择在小区间内放雷达)) t=s[i].r; printf("Case %d: %d\n",++Case, ans); } return 0; }
这就是个区间不相交的问题(按照右焦点从小到大排序,然后排除与第一个区间相交的,依次选择不相交区间即可)
代码:
#include <iostream> #include <algorithm> #include <cstring> #include <string> #include <cstdio> #include <cmath> using namespace std; struct circle { double l,r; }s[1005]; int cmp(circle a,circle b) { return a.r<b.r; } int main() { int sd=0; int n,d; while(~scanf("%d %d",&n,&d)&&(n+d)) { double x,y; int ans=1; for(int i=0;i<n;i++) { scanf("%lf %lf",&x,&y); s[i].l=x-sqrt(d*d-y*y); s[i].r=x+sqrt(d*d-y*y); if(y<0||d<=0||y>d) ans=-1; } sort(s,s+n,cmp); double t=s[0].r; for(int i=1;i<n&&ans!=-1;i++) { if(s[i].l>t) { ans++; t=s[i].r; } } printf("Case %d: %d",++sd,ans); printf("\n"); } return 0; }