原题:Gym-101810K
题意:
你能射出一个宽度为z的气功波,杀死所有边界及边界内的敌人,问n个点中是否可以杀死至少m个点
解析:
对于每个点都作为边界进行判断
- 如果距离原点比较远,那么把气功波的左边界按在这个点上
- 如果比较近,把气功波的下边界按在这个点上
我们通过这个边界求出下边界往左方向的单位向量
- 判断一个点是不是在两条左右边界内:点乘是否小于等于Z/2,就是判断在下边界的投影是否超出范围
- 判断是不是在下边界的上侧:判断(O,P)这个向量逆时针转到单位向量的角度是否小于等于Π
注意,因为精度问题,i==j的情况要拎出来
代码:
F eps=1e-8;
const F pi=acos(-1);
D read(){ D ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
struct point{
F x,y;
point(){}
point(F x,F y):x(x),y(y){}
};
typedef point Vector;
typedef point Point;
Vector operator + (Vector a, Vector b){//向量加法
return Vector(a.x + b.x, a.y + b.y);
}
Vector operator - (Vector a, Vector b){//向量减法
return Vector(a.x - b.x, a.y - b.y);
}
Vector operator * (Vector a, double p){//向量数乘
return Vector(a.x*p, a.y*p);
}
Vector operator / (Vector a, double p){//向量数除
return Vector(a.x / p, a.y / p);
}
int dcmp(double x){//精度三态函数(>0,<0,=0)
if (fabs(x) < eps)return 0;
else if (x > 0)return 1;
return -1;
}
bool operator == (const Point &a, const Point &b){//向量相等
return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
double Dot(Vector a, Vector b){//内积
return a.x*b.x + a.y*b.y;
}
double Length(Vector a){//模
return sqrt(Dot(a, a));
}
double Angle(Vector a, Vector b){//夹角,弧度制
return acos(Dot(a, b) / Length(a) / Length(b));
}
double Cross(Vector a, Vector b){//外积
return a.x*b.y - a.y*b.x;
}
Vector Rotate(Vector a, double rad){//逆时针旋转
return Vector(a.x*cos(rad) - a.y*sin(rad), a.x*sin(rad) + a.y*cos(rad));
}
double Distance(Point a, Point b){//两点间距离
return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}
int n,m;F z;
point p[1009],O;
int main(){
int t=read();
while(t--){
scanf("%d%d%lf",&n,&m,&z);z/=2.0;
for(int i=1;i<=n;i++){
scanf("%lf%lf",&p[i].x,&p[i].y);
}
int ans=0;
for(int i=1;i<=n;i++){
point l=p[i];//the endpoint
if(Length(l)>z)
l=Rotate(l,acos(z/Length(l)));
l=l/Length(l);
int sum=1;
for(int j=1;j<=n;j++)if(i!=j){
if(z>=abs(Dot(p[j],l))){
if(Cross(p[j],l)>=0)sum++;
}
}
ans=max(ans,sum);
}
if(ans>=m)printf("Yes\n");
else printf("No\n");
}
}