题解
- 参考蓝书
- 直线一定经过凸包上的一条边。
- 位于边的一边,所以符号相同。所以预处理x和y的和。
- Ax1 + By1 + C = 0,Ax2 + By2 + C = 0。所以Ax1 + By1 = Ax2 + By2,所以A(x1 - x2) = B(y2 - y1)
- 所以A = y2 - y1,B = x1 - x2,C = -Ax1 - By1
代码
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
const double inf = 1e10;
int const N = 10000 + 10;
int n;
double sumx,sumy;
int dcmp(double x){ //判断符号
if(fabs(x) < eps) return 0;
else return x < 0 ? -1 : 1;
}
typedef struct Point{ //点和向量
double x,y;
Point(){};
Point(double x,double y):x(x),y(y){};
Point operator - (const Point& e)const{ //减
return Point(x - e.x,y - e.y);
}
double operator ^ (const Point& e)const{ //叉乘
return x * e.y - y * e.x;
}
bool operator < (const Point& e)const{ //比较
return x < e.x || x == e.x && y < e.y;
}
}Vector;
double Dot(Vector a,Vector b){
return a.x * b.x + a.y * b.y;
}
Point p[N],ch[N];
int convex(Point *p,int n,Point *ch){
sort(p,p+n);
int m = 0;
for(int i=0;i<n;i++){
while(m > 1 && ((ch[m-1] - ch[m-2]) ^ (p[i] - ch[m-2])) <= 0) m--;
ch[m++] = p[i];
}
int k = m;
for(int i=n-2;i>=0;i--){
while(m > k && ((ch[m-1] - ch[m-2]) ^ (p[i] - ch[m-2])) <= 0) m--;
ch[m++] = p[i];
}
if(n > 1) m--;
return m;
}
double solve(Point *p,int m){
double ans = inf;
for(int i=0;i<m;i++){
int k1 = i, k2 = (i + 1) % m;
double A = p[k2].y - p[k1].y;
double B = p[k1].x - p[k2].x;
double C = -A * p[k1].x - B * p[k1].y;
double up = A * sumx + B * sumy + n * C;
double down = sqrt(A * A + B * B);
ans = min(ans,fabs(up / down));
}
return ans == inf ? 0 : ans;
}
int main(){
int T,caser = 0;
scanf("%d",&T);
while(T--){
sumx = sumy = 0;
scanf("%d",&n);
for(int i=0;i<n;i++){
double x,y;
scanf("%lf%lf",&x,&y);
p[i] = Point(x,y);
sumx += x;
sumy += y;
}
int m = convex(p,n,ch);
printf("Case #%d: %.3f\n",++caser,solve(ch,m) / n); //平均距离最小
}
return 0;
}