问题
https://vjudge.net/problem/UVA-10691
分析
这道题的思路很直接,就是区间选点问题,然后主要是有的区间会小于-pi或者大于pi,引起问题。
注意:如果点到原点的距离小于d就不用往下计算了,直接continue。
别人的解法是将超出pi的区间减去pi,就只剩小于-pi的区间和正常的区间,然后全部加上2*pi,重复一遍,遍历可能的初始点,找出最优解。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long LL;
const int maxn=1000+5;
const double eps=1e-9;
struct Point{
double l,r;
Point(double l=0,double r=0):l(l),r(r){}
bool operator < (const Point &rhs) const {
// if(fabs(r-rhs.r)>eps) return r<rhs.r;
// return l<rhs.l;
return r<rhs.r-eps;
}
}point[maxn];
inline double distant(double x,double y){
return sqrt(x*x+y*y);
}
inline int solve(int x,int cnt){
double cur=-100;
int t=0;
for(int i=x;i<x+cnt;++i){
if(point[i].l-eps<cur) continue;
++t;
cur=max(cur,point[i].r);
}
return t;
}
int n,d,x,y,kase=0,a[maxn],b[maxn];
int main(void){
scanf("%d",&kase);
while(kase--){
scanf("%d%d",&n,&d);
int cnt=0;
for(int i=0;i<n;++i){
scanf("%d%d",&x,&y);
double angle=atan2(y,x);
if(d>=distant(x,y)) continue;
double angle2=asin(d/distant(x,y));
if(angle+angle2>M_PI){
point[cnt++]=Point(angle-angle2-2*M_PI,angle+angle2-2*M_PI);
}else{
point[cnt++]=Point(angle-angle2,angle+angle2);
}
}
sort(point,point+cnt);
for(int i=0;i<cnt;++i){
point[i+cnt].l=point[i].l+2*M_PI;
point[i+cnt].r=point[i].r+2*M_PI;
}
int ans=100000;
for(int i=0;i<cnt;++i){
ans=min(ans,solve(i,cnt));
}
printf("%d\n",ans==100000?0:ans);
}
return 0;
}