乍一看这个问题似乎是很复杂,但其实很好解决。
先处理出每个点到原点的距离和到x正半轴的角度(从x正半轴逆时针旋转的角度)。然后以后者进行排序。
枚举每一个点到圆心的距离,作为半径,并找出其他到圆心距离不超过这个值的点,由于他们的角度是有序的,因此线性的找出角度差最小的满足题意的两个点即可(相当于拿一个长度为k的尺子不断地移动过去)。
那么总的复杂度为O(n^2)。
代码如下(注意atan2的用法):
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <math.h> 5 using namespace std; 6 const int N = 5000 + 5; 7 const double pi = acos(-1); 8 9 int n,k; 10 struct node 11 { 12 int x, y; 13 double angle, dis; 14 void get() 15 { 16 double t = x * x + y * y; 17 //dis = sqrt(t); 18 dis = t; 19 20 angle = atan2(1.0*y, 1.0*x); 21 /*if(y >= 0) 22 { 23 if(x >= 0) 24 { 25 angle = asin(1.0*y / dis); 26 } 27 else 28 { 29 angle = pi - asin(1.0*y / dis); 30 } 31 } 32 else 33 { 34 if(x >= 0) angle = 2.0 * pi - asin(1.0*y / dis); 35 else angle = pi + asin(1.0*y / dis); 36 }*/ 37 } 38 bool operator < (const node & t) const 39 { 40 if(fabs(angle - t.angle) < 1e-8) 41 { 42 return dis < t.dis; 43 } 44 return angle < t.angle; 45 } 46 }p[N]; 47 48 double q[N*2]; 49 50 int main() 51 { 52 int kase = 1; 53 while(scanf("%d%d",&n,&k) == 2) 54 { 55 if(n == 0 && k == 0) break; 56 for(int i=1;i<=n;i++) 57 { 58 scanf("%d%d",&p[i].x,&p[i].y); 59 p[i].get(); 60 } 61 sort(p+1,p+1+n); 62 63 if(k == 0) {printf("Case #%d: 0.00\n",kase++); continue;} 64 65 double ans = 1e10; 66 for(int i=1;i<=n;i++) 67 { 68 double r = p[i].dis; 69 int num = 0; 70 for(int j=1;j<=n;j++) 71 { 72 if(p[j].dis <= r) q[++num] = p[j].angle; 73 } 74 if(num < k) continue; 75 for(int j=1;j<=num;j++) 76 { 77 q[j+num] = 2*pi + q[j]; 78 } 79 for(int j=1;j<=num;j++) 80 { 81 ans = min(ans, r * (q[j+k-1] - q[j]) / 2.0); 82 } 83 } 84 printf("Case #%d: %.2f\n",kase++,ans); 85 } 86 return 0; 87 }