问题
https://vjudge.net/problem/UVA-1432
求包含至少K个点的最小面积的扇区。
分析
利用极坐标系,计算每个点的角度和半径大小,然后枚举l,r,注意,角度是个环形。
这一题一定要先枚举半径,再角度,不能反过来。
小技巧:记录半径的平方而不是半径。
扇形公式
S
=
α
2
r
2
S=\frac{\alpha}{2}r^2
S=2αr2,记住要除以2
注意K==0的情况
#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=5000+5;
const double eps=1e-6;
struct Point{
double angle;
int r;
bool operator < (const Point &rhs) const {
return angle<rhs.angle;
}
}point[maxn];
int N,K,kase=0,a[maxn],x,y;
Point subp[2*maxn];
int main(void){
while(scanf("%d%d",&N,&K)==2 && N){
for(int i=0;i<N;++i){
scanf("%d%d",&x,&y);
point[i].angle=atan2(y,x);
point[i].r=a[i]=x*x+y*y;
}
if(K==0) {
printf("Case #%d: %.2lf\n",++kase,0.0);
continue;
}
sort(a,a+N);
int cnt=unique(a,a+N)-a;
double ans=1e10;
sort(point,point+N);
for(int i=0;i<cnt;++i){
int p=0;
for(int j=0;j<N;++j){
if(point[j].r<=a[i]){
subp[p++]=point[j];
}
}
if(p<K) continue;
int t=p;
double minangle=100;
for(int j=0;j<t;++j) {subp[p]=subp[j]; subp[p].angle+=2*M_PI; ++p;}
for(int j=0;j<t;++j){
if(j+K-1<p)
minangle=min(minangle,subp[j+K-1].angle-subp[j].angle);
else break;
}
ans=min(ans,minangle*a[i]/2);
}
printf("Case #%d: %.2lf\n",++kase,ans);
}
return 0;
}