UVA11168:点到直线的距离 + 凸包

UVA11168

题解

  • 参考蓝书
  • 直线一定经过凸包上的一条边。
  • 位于边的一边,所以符号相同。所以预处理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;
}

猜你喜欢

转载自blog.csdn.net/weixin_42264485/article/details/89059362
今日推荐