標籤:
題意:給定一個數 n 個點,和一個d,要求在x軸上選出盡量少的點,使得對於給定的每個點,都有一個選出的點離它的歐幾裡德距離不超過d。
析:首先這是一個貪心的題目,並且是區間選點問題,什麼是區間選點呢,就是說在數軸上有 n 個閉區間,取盡量少的點,使得每個區間都至少有一個點。
一看是不是和這個題很相似,是的,那麼區間哪裡來呢?自己造唄,既然說是距離不超過d,意思就是在給定的點為圓心,以 d 為半徑畫圓,在x軸上的區間,
那麼區間不就有了麼,然後這個怎麼貪心呢,是這樣的,把所有的區間的右端點從小到大排序(如果相同,則左端點從大到小排),那麼貪心策略就是一定取最後一個點,
也就是右端點,想一想為什麼,也很好理解,盡量讓多的區間都有這個點。那麼這個題就很簡單了。
代碼如下:
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;const int maxn = 1E5 + 5;struct node{ double l, r; bool operator < (const node &p) const{ return r < p.r || (r == p.r && l > p.l);//排序 }};node a[maxn];int main(){// freopen("in.txt", "r", stdin); int n; double x, y, l, d; while(scanf("%lf", &l) == 1){//l 並沒有發現有什麼用 scanf("%lf %d", &d, &n); for(int i = 0; i < n; ++i){ scanf("%lf %lf", &x, &y); a[i].l = x - sqrt(d*d - y*y);//計算左端點 a[i].r = x + sqrt(d*d - y*y);//計算右端點 } sort(a, a+n); int cnt = 1; double ans = a[0].r;//取最後一個點 for(int i = 0; i < n; ++i) if(a[i].l > ans){//如果這個不包含了,先下一個右端點 ++cnt; ans = a[i].r; } printf("%d\n", cnt); } return 0;}
UVa 1615 Highway (貪心,區間選點問題)