【POJ - 1328】Radar Installation(贪心+计算几何)安装雷达辐射岛屿
題干:
Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. Each small island is a point locating in the sea side. And any radar installation, locating on the coasting, can only cover d distance, so an island in the sea can be covered by a radius installation, if the distance between them is at most d.?We use Cartesian coordinate system, defining the coasting is the x-axis. The sea side is above x-axis, and the land side below. Given the position of each island in the sea, and given the distance of the coverage of the radar installation, your task is to write a program to find the minimal number of radar installations to cover all the islands. Note that the position of an island is represented by its x-y coordinates.?
?
Figure A Sample Input of Radar Installations
Input The input consists of several test cases. The first line of each case contains two integers n (1<=n<=1000) and d, where n is the number of islands in the sea and d is the distance of coverage of the radar installation. This is followed by n lines each containing two integers representing the coordinate of the position of each island. Then a blank line follows to separate the cases.?
The input is terminated by a line containing pair of zeros?
Output For each test case output one line consisting of the test case number followed by the minimal number of radar installations needed. "-1" installation means no solution for that case. Sample Input 3 2 1 2 -3 1 2 11 2 0 20 0 Sample Output Case 1: 2 Case 2: 1
題目大意:
? ? 在x軸上建造雷達,似的x軸上方的所有島嶼都能被輻射到。每個雷達的輻射半徑已知,求:為使所有島嶼都被輻射到,所需要的最少雷達個數。
解題報告:
? ? 這應該說是我遇到的第二個不算很水的計算幾何問題,上一個是 解救雅典娜,用dp做,這一題是用貪心做。先按照x坐標從小到大排序,先確定一個半完成值(half-finish自己取的名,第一次使用是在這里)圓心setx,然后逐個遍歷圓心curx(這里取右圓心)(因為圓的半徑已知為d,所以圓心的x軸坐標顯然可求),如果curx<=setx 顯然要取curx 為圓心的那個圓,因為這樣兩個島嶼都會被包進去。如果curx>setx 那就要比較一下該點到圓心setx的距離是否大于d,如果小于等于d,那虛驚一場可以輻射到這個島,如果大于d,那涼涼,只能新建一個雷達了所以ans++。遍歷完所有島嶼即可得出答案ans。(但是總覺得不嚴謹,因為你雖然這個點(記為A)到圓心(記為setx1)的距離大于d了,你就更新了setx(更新為setx2),但有可能下一個點(記為B)滿足curx>setx1&&到圓心的距離<=d呢?,所以不應該這么著急著更新setx吧,,,因為你不確定B是不是也不滿足小于等于d這個要求啊)
對上面問題的回答:是這樣的,確實保證不了,但是因為你已經有一個A滿足不了了,所以無論如何你也要為了A島嶼而建立一個雷達,而這個新雷達能否包含B就看B這個的坐標了。。。即:題目只問的是最少需要建幾個雷達,而非讓你把每個島嶼屬于哪個雷達說清楚,因此沒必要考慮這些問題。
ac代碼:
#include<cstring> #include<cstdio> #include<iostream> #include<algorithm> #include<cmath> using namespace std;struct Node {int x, y; } node[1000 + 5];bool cmp(const Node & a,const Node & b) {return a.x<b.x;//此題y坐標排不排序無所謂的、、、 }int main() {int n,d;int ans=1;int maxy;int iCase=0;double curx,setx,seti;//curx表示當前嘗試的右圓心 setx表示當前確定的右圓心 seti表示當前確定的索引值 double curd;//curd表示當前嘗試的圓的半徑 while(scanf("%d %d",&n,&d)) {ans=1;maxy=0;//別忘了初始化! ! if(n==0 && d==0) break;for(int i = 0; i<n; i++) {scanf("%d %d",&node[i].x,&node[i].y); maxy=max(node[i].y,maxy);}if(maxy>d) {printf("Case %d: -1\n" , ++iCase);continue;}sort(node,node+n,cmp);curx=node[0].x+sqrt(d*d-( node[0].y )*( node[0].y ) );setx=curx;seti=0;for(int i = 1; i<n; i++) {//因為第一個已經初始化好了,所以下標從1開始 curx=node[i].x+sqrt(d*d-( node[i].y )*( node[i].y ) );if(curx<=setx) {setx=curx;}else {curd=sqrt( (node[i].x-setx)*(node[i].x-setx) +(node[i].y)*(node[i].y) );if(curd<=d) {continue;}else {ans++;setx=curx;}}} printf("Case %d: %d\n",++iCase,ans);} return 0 ; }下面附上kuangbin大佬的代碼:(其實差不多的只不過我是用的點到setx的距離d,他是用的點的左圓心)
#include<stdio.h> #include<iostream> #include<math.h> #include<algorithm>//sort所在的庫文件,排序用 using namespace std; const int MAXN=1005; struct Line {double l,r; }line[MAXN];//每個島作半徑為d的圓,與x軸所截的線段bool cmp(Line a,Line b) {return a.l<b.l; } //按照線段的左端點從小到大排序 int main() {//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);int n,d;int i;int x,y;bool yes;//確定是不是有解int icase=1;while(cin>>n>>d){yes=true;int cnt=0;if(n==0&&d==0)break;for(i=0;i<n;i++){cin>>x>>y;if(yes==false)continue;if(y>d)yes=false;else{line[i].l=(double)x-sqrt((double)d*d-y*y);line[i].r=(double)x+sqrt((double)d*d-y*y);} }if(yes==false){cout<<"Case "<<icase++<<": -1"<<endl;continue;}sort(line,line+n,cmp);cnt++;double now=line[0].r;for(i=1;i<n;i++){if(line[i].r<now)//這點很重要 now=line[i].r;else if(now<line[i].l){now=line[i].r;cnt++;} }cout<<"Case "<<icase++<<": "<<cnt<<endl; } return 0; }總結
以上是生活随笔為你收集整理的【POJ - 1328】Radar Installation(贪心+计算几何)安装雷达辐射岛屿的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pccntmon.exe进程是什么文件
- 下一篇: Coursera自动驾驶课程第17讲:A