链接
http://acm.hdu.edu.cn/showproblem.php?pid=2469
题解
本来以为是一道很简单的休闲题,结果调试了一晚上+一上午
其实算法没什么难的,因为最小扇形的半径肯定等于某个点到原点的距离,所以直接
O(n)
O
(
n
)
枚举半径,然后
O(n)
O
(
n
)
扫描一下就行了,时间复杂度
O(n2)
O
(
n
2
)
一个技巧就是,把整个数组复制一遍,后面的那一段的角度加上
2π
2
π
,这样就好处理很多
一个很可恶的事情就是,
k
k
可能等于,我就是没注意到这一点,才
WA
W
A
的要死
话说
k=0
k
=
0
真的有意义吗??
代码
//几何题
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <cmath>
#define maxn 5010
#define inf 1e60
#define eps 1e-8
#define sqr(x) ((x)*(x))
#define PI 3.1415926535897932384626433832795
using namespace std;
struct point
{
int x, y, r2;
double theta;
void init(){theta=atan2(y,x);r2=sqr(x)+sqr(y);}
bool operator<(point a){return theta<a.theta-eps;}
}pt[maxn<<1];
int n, k;
double ans;
int read(int x=0)
{
char c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
return f*x;
}
void init()
{
int i;
for(i=1;i<=n;i++)pt[i].x=read(), pt[i].y=read(), pt[i].init();
sort(pt+1,pt+n+1);
for(i=1;i<=n;i++)pt[n+i]=pt[i], pt[n+i].theta+=2*PI;
}
void work()
{
int i, j, p1, p2, cnt, alpha, r2;
ans=inf;
for(i=1;i<=n;i++)
{
r2=pt[i].r2;
for(p1=1, p2=2, cnt=pt[1].r2<=r2;p1<=n;p1++)
{
for(;cnt<k and p2<p1+n;p2++)if(pt[p2].r2<=r2)cnt++;
if(cnt==k)ans=min(ans,(pt[p2-1].theta-pt[p1].theta)*r2/2.0);
if(pt[p1].r2<=r2)cnt--;
}
}
}
int main()
{
int c;
for(n=read(),k=read(),c=1;n;n=read(),k=read(),c++)
{
printf("Case #%d: ",c);
init();
if(k==0)ans=0;
else work();
printf("%.2lf\n",ans+eps);
}
return 0;
}