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

UVA 11168 Airport(凸包+直线方程)

2016-02-01 17:06 393 查看
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34780

【思路】

凸包+直线方程。

求出点集的凸包,则题目所求直线必在凸包的边上。

如果已知边的直线表达式为Ax+By+C,则距离和为:



直线两点式为:



简单化化就可以搞出一般式了。

【代码】

#include<cmath>
#include<vector>
#include<cstdio>
#include<algorithm>
using namespace std;

const double eps = 1e-10;
int dcmp(double x) {
if(fabs(x)<eps) return 0; else return x<0? -1:1;
}

struct Pt {
double x,y;
Pt(double x=0,double y=0):x(x),y(y) {};
};
typedef Pt vec;
vec operator - (Pt A,Pt B) { return vec(A.x-B.x,A.y-B.y); }
bool operator == (Pt A,Pt B) {
return dcmp(A.x-B.x)==0 && dcmp(A.y-B.y)==0;
}
bool operator < (const Pt& a,const Pt& b) {
return a.x<b.x || (a.x==b.x && a.y<b.y);
}
double cross(Pt A,Pt B) { return A.x*B.y-A.y*B.x; }

int n;
vector<Pt> ConvexHull(vector<Pt> p) {
sort(p.begin(),p.end());
p.erase(unique(p.begin(),p.end()),p.end());
vector<Pt> ch(n+1);
int n=p.size();
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--;
ch.resize(m);
return ch;
}

void getLineEquation(Pt a,Pt b,double& A,double& B,double& C) {
A=b.y-a.y; B=a.x-b.x;
C=-a.x*A - a.y*B;
}

int main() {
int T,kase=0;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
vector<Pt> P,ch;
double x,y,sx=0,sy=0,A,B,C;
for(int i=0;i<n;i++) {
scanf("%lf%lf",&x,&y);
sx+=x , sy+=y;
P.push_back(Pt(x,y));
}
ch=ConvexHull(P);
double ans=1e15;
if(ch.size()<=2) ans=0;
for(int i=0;i<ch.size();i++) {
getLineEquation(ch[i],ch[(i+1)%ch.size()],A,B,C);
double res=fabs((A*sx+B*sy+C*n)/(sqrt(A*A+B*B)));
if(res<ans) ans=res;
}
printf("Case #%d: %.3lf\n",++kase,ans/n);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: