1. 程式人生 > >C - 安裝雷達

C - 安裝雷達

C - 安裝雷達

Time Limit: 1000/1000MS (C++/Others) Memory Limit: 65536/65536KB (C++/Others)

Problem Description

我們假設海岸線是一條無限直線:以海岸線為界,陸地和海洋被分開,在海邊分佈著很多小島。現在,我們在海岸線上安裝雷達,每個雷達有固定的通訊範圍(以d為半徑的圓形區域),這樣,海邊的小島就可以被某個雷達訊號覆蓋。
這裡我們使用笛卡爾座標系,定義海岸線為x軸,x軸上方是海洋,下方是陸地。給出分佈在海邊每個小島的座標位置和雷達訊號能覆蓋的範圍d,你的任務是計算出最小需要安裝的雷達數目,使得這些雷達訊號能覆蓋到所有海邊的小島。每個小島的座標格式為(x,y)。
如下圖所示,給出第一個輸入樣例的座標表示,這樣在(-2,0),(1,0)上分別安裝雷達就可以覆蓋所有的小島(p點),所以我們只需要安裝2個雷達。

Input

輸入包含多組測試樣例。每組測試第一行包含兩個整數n(1<=n<=1000)和d,n表示小島的數目,d表示雷達能覆蓋的範圍的半徑。接下來n行,每行由整數x和y組成,表示n個小島的座標位置。每兩組資料之間有一個空行。
輸入0 0表示輸入的結束。

Output

對於每一組輸入,按照輸出樣例中的格式輸出:包含輸出序號和最少需要安裝雷達的數目。如果找不到解決方案,即不能找到一種安裝方案覆蓋所有的小島,輸出”-1”。

Sample Input

3 2
1 2
-3 1
2 1

1 2
0 2

0 0

Sample Output

Case 1: 2
Case 2: 1





#include<cstdio>
#include<cmath>
#include<algorithm>
#define fi first  // 巨集定義 為了程式碼簡便
#define se second // 分別表示pair中的第一個數和第二個數
using namespace std;
const int maxn = 1e5+5;

pair<double, double> a[maxn];

int main() { int n, d, cs = 1; while(~scanf("%d%d", &n, &d) && n){ double x, y; bool can = true; for(int i=0; i<n; i++){ scanf("%lf%lf", &x, &y); if(y > d || y < -d) { // 無法覆蓋的點 can = false; continue; } a[i].fi = x - sqrt(d*d - y*y); // 可覆蓋第i個點,在x軸上最左側的位置 a[i].se = x + sqrt(d*d - y*y); // 可覆蓋第i個點,在x軸上最右側的位置 } printf("Case %d: ", cs++); if(!can) { puts("-1"); continue; } int cnt = 1; sort(a, a+n); // 預設按照第一個數升序優先,第二個數升序的順序排序 pair<double, double> now = a[0]; // 初始化可用區間 for(int i=1; i<n; i++){ if(now.se < a[i].fi) { // 當前區間不能覆蓋a[i] 更新可能區間 cnt ++; now = a[i]; } else if(now.se > a[i].se) now = a[i]; // 當前區間過大,需要減小可用區間 } printf("%d\n", cnt); } return 0; }