UVA 11168 Airport

本文介绍了一个算法问题,即如何确定一条直线的位置,使得平面上多个点到这条直线的距离之和最小,并确保所有点位于直线同一侧。通过计算凸包并遍历其边界,找到最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

There is a small town with n houses. The town needs an airport. An airport is basically a very long, very straight road. Think of it as an infinite line. We need to build the airport such that the average distance from each house to the airport is as small as possible. However, no one wants to walk across the runway, so all of the houses must be on the same side of the airport. (Some houses may be a distance of zero away from the runway, but that's ok; we'll give them some free ear plugs.)

Where should we build the airport, and what will be the average distance?

Input
The first line of input gives the number of cases, N (<=65) . N test cases follow. Each one is a line containing n (0 < n <= 10000) , followed by n lines giving the xy-coordinates of the houses. All coordinates are integers with absolute value of at most 80,000 .
Output

For each test case, output one line containing "Case #x:" followed by the average distance from the airport to the houses, with 3 digits after the decimal point. No answer will be within 10-5 of a round-off error case.

Sample Input                             Output for Sample Input

4 
4 
0 0
0 1 
1 0 
1 1
2 
15035 39572 
34582 39535 
3 
0 0
0 1 
1 0 
5 
0 0
0 2 
2 0 
2 2
11
Case #1: 0.500 
Case #2: 0.000 
Case #3: 0.236 
Case #4: 1.000 


给出平面上的n个点,求一条直线,使得所有点在该直线的同一侧且所有点到该直线的距离和最小,输出该距离和。

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

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


#include <iostream>
#include <algorithm>
#include <math.h>
#include <iomanip>
using namespace std;
struct Point
{
    double x,y;
    Point(){}
    Point(double x,double y):x(x),y(y){}
} ;
bool operator < (const Point&a,const Point&b)
{
    return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
Point operator+(Point A,Point B)
{
    return Point(A.x+B.x,A.y+B.y);
}
Point operator-(Point A,Point B)
{
    return Point(A.x-B.x,A.y-B.y);
}
double Cross(Point A,Point B)
{
    return A.x*B.y-A.y*B.x;
}
void GetLineABC(Point A,Point B,double &a,double &b,double &c)//直线两点式转一般式
{
    a=A.y-B.y; b=B.x-A.x; c=A.x*B.y-A.y*B.x;
}
int ConvexHull(Point *p,int n,Point *ch)
{
    sort(p,p+n);
    int m=0;
    for(int i=0;i<n;i++)
    {
        while(m>1&&Cross(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&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;
        ch[m++]=p[i];
    }
    if(n>1)m--;
    return m;
}


int main()
{
    int T;
    cin>>T;
    for(int cases=1;cases<=T;cases++)
    {
        int N;
        Point P[10010],ch[10010];
        cin>>N;
        double X=0,Y=0,ans=1e10;
        for(int i=0;i<N;i++)
        {
              cin>>P[i].x>>P[i].y;
              X=X+P[i].x;
              Y=Y+P[i].y;
        }
        int m=ConvexHull(P,N,ch);
        ch[m]=ch[0];
        for(int i=0;i<m;i++)
        {
            double a=0,b=0,c=0;
            GetLineABC(ch[i],ch[i+1],a,b,c);
            ans=min(ans,fabs(a*X+b*Y+c*N)/(sqrt(a*a+b*b)));
        }
        cout<<setiosflags(ios::fixed)<<setprecision(3);
        cout<<"Case #"<<cases<<": "<<(N>2?ans/N:0)<<endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值