1 /*UVA 11168计算几何 2 凸包+数学思维 3 在直线同一侧的点,带入直线方程后,正负性是一致的,这个是解题的关键 4 所以运用点到直线的距离公式,可以O(1)计算出距离,枚举出最短距离即可 5 这里比较容易犯错的是:1、点斜式竖线无意义(也可用精度处理掉)2、点到直线的距离公式 6 */ 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <math.h> 11 #include <ctype.h> 12 #include <string> 13 #include <iostream> 14 #include <sstream> 15 #include <vector> 16 #include <queue> 17 #include <stack> 18 #include <map> 19 #include <list> 20 #include <set> 21 #include <algorithm> 22 #define INF 0x3f3f3f3f 23 #define eps 1e-7 24 #define eps2 1e-3 25 #define zero(x) (((x)>0?(x):-(x))<eps) 26 using namespace std; 27 28 29 struct Point 30 { 31 double x,y; 32 Point() {} 33 Point(double xx,double yy) 34 { 35 x=xx; 36 y=yy; 37 } 38 bool operator<(const Point& p) const{ 39 if (x==p.x) return y<p.y; 40 else return x<p.x; 41 } 42 }P1[10505],P2[10505]; 43 44 typedef Point Vector; 45 46 bool operator==(Point A,Point B) 47 { 48 if ((fabs(A.x-B.x)<eps) && (fabs(A.y-B.y)<eps)) return true; 49 else return false; 50 } 51 Vector operator-(Point A,Point B)//表示A指向B 52 { 53 return Vector(A.x-B.x,A.y-B.y); 54 } 55 Vector operator*(Vector A,double k) 56 { 57 return Vector(A.x*k,A.y*k); 58 } 59 Vector operator+(Point A,Point B)//表示A指向B 60 { 61 return Vector(B.x+A.x,B.y+A.y); 62 } 63 double Cross(Vector A,Vector B) 64 { 65 return A.x*B.y-A.y*B.x; 66 } 67 double Area2(Point A,Point B,Point C) 68 { 69 return Cross(B-A,C-A); 70 } 71 //p是原先点的数组,n是个数,ch是凸包的点集 72 //精度要求高是用dcmp比较 73 //返回凸包点的个数 74 int ConvexHull(Point *p, int n, Point* ch){ //求凸包 75 sort(p, p + n);//先按照x,再按照y 76 int m = 0; 77 for(int i = 0; i < n; i++){ 78 while(m > 1 && Cross(ch[m-1] - ch[m-2], p[i] - ch[m-2]) < 0) m--; 79 ch[m++] = p[i]; 80 } 81 int k = m; 82 for(int i = n-2; i >= 0; i--){ 83 while(m > k && Cross(ch[m-1] - ch[m-2], p[i] - ch[m-2]) < 0) m--; 84 ch[m++] = p[i]; 85 } 86 if(n > 1) m--; 87 return m; 88 } 89 double ConvexPolygonArea(Point *p, int n){//凸包面积 90 double area = 0; 91 for(int i = 1; i < n-1; i++) area += Area2(p[0], p[i], p[i+1]); 92 return area / 2; 93 } 94 95 double X,Y; 96 int t,n,cnt; 97 98 double getdis(int k) 99 { 100 101 double ans=0; 102 Point p1=P2[k]; 103 Point p2=P2[(k+1)%cnt]; 104 if(fabs(p1.x-p2.x)<eps)//垂直线特判 105 { 106 for(int i=0;i<n;i++)//注意是所有点 107 { 108 double x=P1[i].x; 109 ans+=fabs(x-(p1.x+p2.x)/2);//取中点,减少精度损失 110 } 111 112 }else{//转化成y=kx+b方程 113 double xie=(p1.y-p2.y)/(p1.x-p2.x); 114 if(fabs(xie)<eps) xie=0;//调试中出现了负0 115 double b=p1.y-xie*p1.x; 116 double s=fabs(xie*X+b*n-Y),t=sqrt(xie*xie+1); 117 ans=s/(t+0.0); 118 } 119 return ans; 120 } 121 int main() 122 { 123 124 cin>>t; 125 126 for(int cas=1;cas<=t;cas++) 127 { 128 double ans=9999999999; 129 X=0,Y=0; 130 cin>>n; 131 for(int i=0;i<n;i++) 132 { 133 double x,y;cin>>x>>y; 134 P1[i]=Point(x,y); 135 X+=x,Y+=y; 136 } 137 cnt=ConvexHull(P1,n,P2);//凸包上的点 138 for(int i=0;i<cnt;i++)//枚举直线 139 ans=min(ans,getdis(i)/n); 140 printf("Case #%d: %.3lf ",cas,ans); 141 } 142 return 0; 143 }