1. 程式人生 > 實用技巧 >Acwing 112 雷達裝置 (貪心)

Acwing 112 雷達裝置 (貪心)

題面

假設海岸是一條無限長的直線,陸地位於海岸的一側,海洋位於另外一側。

每個小島都位於海洋一側的某個點上。

雷達裝置均位於海岸線上,且雷達的監測範圍為d,當小島與某雷達的距離不超過d時,該小島可以被雷達覆蓋。

我們使用笛卡爾座標系,定義海岸線為x軸,海的一側在x軸上方,陸地一側在x軸下方。

現在給出每個小島的具體座標以及雷達的檢測範圍,請你求出能夠使所有小島都被雷達覆蓋所需的最小雷達數目。

輸入格式
第一行輸入兩個整數n和d,分別代表小島數目和雷達檢測範圍。

接下來n行,每行輸入兩個整數,分別代表小島的x,y軸座標。

同一行資料之間用空格隔開。

輸出格式
輸出一個整數,代表所需的最小雷達數目,若沒有解決方案則所需數目輸出“-1”。

資料範圍
1≤n≤1000
輸入樣例:
3 2
1 2
-3 1
2 1
輸出樣例:
2

思路

題意就不解釋了。那麼我們剛開始的想法肯定是取考慮怎麼在區間裡面取雷達可以最優,但是呢,你會發現這樣做並不能找到一個最優的策略,這時候我們需要換一個角度看問題。我們考慮一個點可以被哪些雷達覆蓋,你會發現,這些雷達點會構成一個區間,而我們要做的就是區間的選擇,我們要在安排一些點使得每一個區間都有一個點,那麼這個問題就轉換成了一個區間貪心問題。我們按照右端點排序,每次取右端點作為這個區間的點,這樣可以做到貪心的目的,他可以儘可能的滿足後面的點。所以我們在寫貪心的題目的時候不能思維定式,我們要從不同角度看待問題,使得問題最終轉化成為我們熟悉的貪心模型。

程式碼實現

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1010;
const double eps=1e-6,inf=1e10;
typedef pair <double,double > PII; 
int n,d;
PII a[maxn];

int main () {
   cin>>n>>d;
   bool flag=1;
   for (int i=1,x,y;i<=n;i++) {
      cin>>x>>y;
      if (y>d) {
          flag=0;
          break;
      }
      double len=sqrt (d*d-y*y);
      a[i]={x+len,x-len};
   }
   if (!flag)  cout<<-1<<endl;
   else {
       sort (a+1,a+1+n);
       int ans=0;
       double last=-inf;
       for (int i=1;i<=n;i++) {
           if (a[i].second>last+eps) {
               ans++;
               last=a[i].first;
           }
       }
       cout<<ans<<endl;
   }
    return 0;
}