您的位置:首页 > 大数据 > 人工智能

UVa 11168 Airport凸包与直线方程

2014-04-15 14:57 99 查看
题意:给出平面上的n个点,求一条直线,使得所有点在该直线的同一侧且所有点到该直线的距离和最小,输出该距离和。

思路:要使所有点在该直线的同一侧,明显是直接利用凸包的边更优。所以枚举凸包的没条边,然后求距离和。直线一般式为Ax + By + C = 0.点(x0, y0)到直线的距离为

fabs(Ax0+By0+C)/sqrt(A*A+B*B).由于所有点在直线的同一侧,那么对于所有点,他们的(Ax0+By0+C)符号相同,显然可以累加出sumX和sumY,然后统一求和。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 800000000
int sumX, sumY, N;
struct Point{int x, y;};
Point p[10002], ch[10002];
bool cmp(Point a, Point b){
return a.x == b.x ? a.y < b.y : a.x < b.x;
}
int Cross(Point a, Point b, Point c){
return (a.x-c.x)*(b.y-c.y) - (a.y-c.y)*(b.x-c.x);
}
const double eps = 1e-10;
int Dcmp(double x){
if(x < eps)return 0;
return x < 0 ? -1 : 1;
}
int ConvexHull()//凸包
{
sort(p, p+N, cmp);
int m = 0;
for(int i = 0; i < N; i++){
while(m > 1 && Dcmp(Cross(ch[m-1], 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 && Dcmp(Cross(ch[m-1], p[i], ch[m-2])) <= 0)m--;
ch[m++] = p[i];
}
if(N > 1)m--;
return m;
}
double getDist(Point a, Point b){
double A, B, C, k, v;
A = a.y - b.y;
B = b.x - a.x;
C = a.x*b.y - a.y*b.x;
k = fabs(A*sumX + B*sumY + N * C);
v = sqrt(A * A + B * B);
return k / v;
}
double Line(int m)
{
double minL = INF*1.0, L;
for(int i = 0; i < m; i++){
L = getDist(ch[i], ch[(i+1)%m]);//得到所有点到凸包一条边的距离
minL = min(minL, L);
}
return minL;
}
int main()
{
int i, j, t;
cin>>t;
int cas = 1;
while(t--)
{
cin>>N;
sumX = sumY = 0;
for(i = 0; i < N; i++){
scanf("%d%d", &p[i].x, &p[i].y);
sumX += p[i].x;
sumY += p[i].y;
}
printf("Case #%d: ", cas++);
if(N == 1 || N== 2){
printf("0.000\n");
continue;
}
printf("%.3lf\n", Line( ConvexHull() ) / (N*1.0));
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: