题目:
给定平面上n(n≤105)个点和一个值D,要求在x轴上选出尽量少的点,使得对于给定的每个点,都有一个选出的点离它的欧几里得距离不超过D。
思路:
先自己造区间,然后贪心选点就可以了。之前做过一到类似的题目还是没有一眼看出来。
区间的造法,就是以给出的点为圆心,以D为半径画圆,这个圆与x轴的相交的两个点就是我们造的区间的左右两个端点。
然后以右端点从小到大排序贪心。(自己举了一个例子发现左端点要比右端点多)
代码:
#include <bits/stdc++.h> #define inf 0x3f3f3f3f #define MAX 1e3 #define FRE() freopen("in.txt","r",stdin) #define FRO() freopen("out.txt","w",stdout) using namespace std; typedef long long ll; typedef pair<int, int> P; const int maxn = 100010; double L,D; int n; struct Region{ double l, r; }reg[maxn]; double dist(double y){ return sqrt(D*D-y*y); } bool cmd(Region a,Region b){ return a.r<b.r; } int main(){ //FRE(); while(scanf("%lf",&L)!=EOF){ scanf("%lf",&D); scanf("%d",&n); for(int i=0; i<n; i++){ double x,y; scanf("%lf%lf",&x,&y); reg[i].l = max(x-dist(y),0.0); reg[i].r = min(x+dist(y),L); } sort(reg,reg+n,cmd); int ans = 0,pos = -1; for(int i=0; i<n; i++){ if(pos<reg[i].l||pos>reg[i].r){ ans++; pos = reg[i].r; } } printf("%d\n",ans); } return 0; }