POJ 1328
是說在海岸線上怎麼樣才能見最少的雷達覆蓋海中的島嶼,該題轉化爲數學問題就是在x軸上找最少的點,使之可以覆蓋平面上給出的一定數量的點。
思路就是通過找出每個海島放置雷達的左右區間xl,xr,再按照區間左值xl排序,然後遍歷,當發現下一個端點的xl小於前面已經完成的區間最小右值時,計數器加1,維護最小右值即可。找區間的做法就是以海島爲圓心,雷達覆蓋的距離爲半徑,與x軸相交的兩點分別是xl,xr。
附上代碼以及部分測試數據:
#define MAXN 1005
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
typedef struct
{
int x,y;
}intpoint;//定義儲存點的結構體
typedef struct
{
double xl,xr;
}doupoint;//定義儲存左右值類型的結構體,double
intpoint lca[MAXN];
doupoint lr[MAXN];
int n,d,counter;
bool cmp(doupoint a,doupoint b)
{
return a.xl<b.xl;
}
bool workout_lr()
{
int i;
double min,te;
for(i=1;i<=n;i++)
{
if(lca[i].y>d || lca[i].y<-1*d)
return false;//遇到不可能的情況,直接跳出
te=sqrt(1.0*(d*d-lca[i].y*lca[i].y));
lr[i].xr=lca[i].x+te;//求出左右值
lr[i].xl=lca[i].x-te;
}
sort(lr+1,lr+n+1,cmp);
counter=1;min=lr[1].xr;
for(i=1;i<=n;i++)
{
if(lr[i].xl>min){//更新並計數
counter++;
min=lr[i].xr;
}
else if(lr[i].xr<min)
min=lr[i].xr;
}
return true;
}
void solve()
{
int i,test=1;
while(scanf("%d %d",&n,&d)==2)
{
if(n==0 && d==0) break;
for(i=1;i<=n;i++) scanf("%d %d",&lca[i].x,&lca[i].y);
//sort(lca+1,lca+n+1,cmp);
printf("Case %d: ",test++);
if(workout_lr()) printf("%d\n",counter);
else printf("-1\n");
}
}
int main()
{
solve();
return 0;
}