UVA 11168 - Airport - [凸包基础题]
题目链接:https://cn.vjudge.net/problem/UVA-11168
题意:
给出平面上的n个点,求一条直线,使得所有的点在该直线的同一侧(可以在该直线上),并且所有点到该直线的距离和最小,输出该距离除以n;
题解:
显然最好能让越多的点在这条直线上就越好,但又要所有点满足在同侧,则显然要选取某条凸包边界所在直线作为ans;
求出凸包后,遍历每条凸包边,求出所有点到这条直线的距离和,找到最小的即可。
AC代码:
#include<bits/stdc++.h>
#define MAX 10005
using namespace std; //--------------------------------------计算几何模板 - st-------------------------------------- const double eps = 1e-; struct Point{
double x,y;
Point(double tx=,double ty=):x(tx),y(ty){}
};
typedef Point Vctor; //向量的加减乘除
Vctor operator + (Vctor A,Vctor B){return Vctor(A.x+B.x,A.y+B.y);}
Vctor operator - (Point A,Point B){return Vctor(A.x-B.x,A.y-B.y);}
Vctor operator * (Vctor A,double p){return Vctor(A.x*p,A.y*p);}
Vctor operator / (Vctor A,double p){return Vctor(A.x/p,A.y/p);}
bool operator < (Point A,Point B){return A.x < B.x || (A.x == B.x && A.y < B.y);} struct Line{
Point p;
Vctor v;
Line(Point p=Point(,),Vctor v=Vctor(,)):p(p),v(v){}
Point point(double t){return p + v*t;} //获得直线上的距离p点t个单位长度的点
};
struct Circle{
Point c;
double r;
Circle(Point tc=Point(,),double tr=):c(tc),r(tr){}
Point point(double a){return Point( c.x + cos(a)*r , c.y + sin(a)*r);}
}; int dcmp(double x)
{
if(fabs(x)<eps) return ;
else return (x<)?(-):();
}
bool operator == (Point A,Point B){return dcmp(A.x-B.x)== && dcmp(A.y-B.y)==;} //向量的点积,长度,夹角
double Dot(Vctor A,Vctor B){return A.x*B.x+A.y*B.y;}
double Length(Vctor A){return sqrt(Dot(A,A));}
double Angle(Vctor A,Vctor B){return acos(Dot(A,B)/Length(A)/Length(B));} //叉积,三角形面积
double Cross(Vctor A,Vctor B){return A.x*B.y-A.y*B.x;}
double TriangleArea(Point A,Point B,Point C){return Cross(B-A,C-A);} //向量的旋转,求向量的单位法线(即左转90度,然后长度归一)
Vctor Rotate(Vctor A,double rad){return Vctor( A.x*cos(rad) - A.y*sin(rad) , A.x*sin(rad) + A.y*cos(rad) );}
Vctor Normal(Vctor A)
{
double L = Length(A);
return Vctor(-A.y/L, A.x/L);
} //直线的交点
Point getLineIntersection(Line L1,Line L2)
{
Vctor u = L1.p-L2.p;
double t = Cross(L2.v,u)/Cross(L1.v,L2.v);
return L1.p + L1.v*t;
} //点到直线的距离
double DistanceToLine(Point P,Line L)
{
return fabs(Cross(P-L.p,L.v))/Length(L.v);
} //点到线段的距离
double DistanceToSegment(Point P,Point A,Point B)
{
if(A==B) return Length(P-A);
Vctor v1 = B-A, v2 = P-A, v3 = P-B;
if (dcmp(Dot(v1,v2)) < ) return Length(v2);
else if (dcmp(Dot(v1,v3)) > ) return Length(v3);
else return fabs(Cross(v1,v2))/Length(v1);
} //点到直线的映射
Point getLineProjection(Point P,Line L)
{
return L.v + L.v*Dot(L.v,P-L.p)/Dot(L.v,L.v);
} //判断线段是否规范相交
bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2)
{
double c1 = Cross(a2 - a1,b1 - a1), c2 = Cross(a2 - a1,b2 - a1),
c3 = Cross(b2 - b1,a1 - b1), c4 = Cross(b2 - b1,a2 - b1);
return dcmp(c1)*dcmp(c2)< && dcmp(c3)*dcmp(c4)<;
} //判断点是否在一条线段上
bool OnSegment(Point P,Point a1,Point a2)
{
return dcmp(Cross(a1 - P,a2 - P))== && dcmp(Dot(a1 - P,a2 - P))<;
} //多边形面积
double PolgonArea(Point *p,int n)
{
double area=;
for(int i=;i<n-;i++) area += Cross( p[i]-p[] , p[i + ]-p[] );
return area/;
} //判断圆与直线是否相交以及求出交点
int getLineCircleIntersection(Line L,Circle C,vector<Point> &sol)
{
double t1,t2;
double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y - C.c.y;
double e = a*a + c*c , f = *(a*b + c*d), g = b*b + d*d - C.r*C.r;
double delta = f*f - 4.0*e*g;
if(dcmp(delta)<) return ;
else if(dcmp(delta)==)
{
t1 = t2 = -f/(2.0*e);
sol.push_back(L.point(t1));
return ;
}
else
{
t1 = (-f-sqrt(delta))/(2.0*e); sol.push_back(L.point(t1));
t2 = (-f+sqrt(delta))/(2.0*e); sol.push_back(L.point(t2));
return ;
}
} //判断并求出两圆的交点
double angle(Vctor v){return atan2(v.y,v.x);}
int getCircleIntersection(Circle C1,Circle C2,vector<Point> &sol)
{
double d = Length(C1.c - C2.c);
//圆心重合
if(dcmp(d)==)
{
if(dcmp(C1.r-C2.r)==) return -; //两圆重合
else return ; //包含关系
} //圆心不重合
if(dcmp(C1.r+C2.r-d)<) return ; // 相离
if(dcmp(fabs(C1.r-C2.r)-d)>) return ; // 包含 double a = angle(C2.c - C1.c);
double da = acos((C1.r*C1.r + d*d - C2.r*C2.r) / (*C1.r*d));
Point p1 = C1.point(a - da), p2 = C1.point(a + da);
sol.push_back(p1);
if(p1==p2) return ;
sol.push_back(p2);
return ;
} //求点到圆的切线
int getTangents(Point p,Circle C,vector<Line> &sol)
{
Vctor u=C.c-p;
double dis=Length(u);
if(dis<C.r) return ;
else if(dcmp(dis-C.r) == )
{
sol.push_back(Line(p,Rotate(u,M_PI/)));
return ;
}
else
{
double ang=asin(C.r/dis);
sol.push_back(Line(p,Rotate(u,-ang)));
sol.push_back(Line(p,Rotate(u,ang)));
return ;
}
} //求两圆的切线
int getCircleTangents(Circle A,Circle B,Point *a,Point *b)
{
int cnt = ;
if(A.r<B.r){swap(A,B);swap(a,b);}
//圆心距的平方
double d2 = (A.c.x - B.c.x)*(A.c.x - B.c.x) + (A.c.y - B.c.y)*(A.c.y - B.c.y);
double rdiff = A.r - B.r;
double rsum = A.r + B.r;
double base = angle(B.c - A.c);
//重合有无限多条
if(d2 == && dcmp(A.r - B.r) == ) return -;
//内切
if(dcmp(d2-rdiff*rdiff) == )
{
a[cnt] = A.point(base);
b[cnt] = B.point(base);
cnt++;
return ;
}
//有外公切线
double ang = acos((A.r - B.r) / sqrt(d2));
a[cnt] = A.point(base + ang); b[cnt] = B.point(base + ang); cnt++;
a[cnt] = A.point(base - ang); b[cnt] = B.point(base - ang); cnt++; //一条内切线
if(dcmp(d2-rsum*rsum) == )
{
a[cnt] = A.point(base);
b[cnt] = B.point(M_PI + base);
cnt++;
}//两条内切线
else if(dcmp(d2-rsum*rsum) > )
{
double ang = acos((A.r + B.r) / sqrt(d2));
a[cnt] = A.point(base + ang); b[cnt] = B.point(base + ang); cnt++;
a[cnt] = A.point(base - ang); b[cnt] = B.point(base - ang); cnt++;
}
return cnt;
} //--------------------------------------计算几何模板 - ed--------------------------------------
Point p[MAX]; bool cmp(Point p1,Point p2)
{
double tmp=Cross(p1-p[],p2-p[]);
if(!dcmp(tmp)) return Length(p1-p[])<Length(p2-p[]);
else return tmp>;
}
vector<Point> graham_scan(int n)
{
vector<Point> ans;
int idx=;
for(int i=;i<n;i++)//选出Y坐标最小的点,若Y坐标相等,选择X坐标小的点
{
if(p[i].y<p[idx].y || (p[i].y == p[idx].y && p[i].x < p[idx].x)) idx=i;
}
swap(p[],p[idx]);
sort(p+,p+n,cmp);
for(int i=;i<=;i++) ans.push_back(p[i]);
int top=;
for(int i=;i<n;i++)
{
while(top> && Cross(p[i]-ans[top-],ans[top]-ans[top-]) >= )
{
ans.pop_back();
top--;
}
ans.push_back(p[i]);
top++;
}
return ans;
} int n;
int main()
{
int t;
scanf("%d",&t);
for(int kase=;kase<=t;kase++)
{
scanf("%d",&n);
for(int i=;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
vector<Point> ans=graham_scan(n);
double mini=0x3f3f3f3f;
for(int i=;i<ans.size();i++)
{
Point& p1 = ans[i];
Point& p2 = (i==ans.size()-)?ans[]:ans[i+];
double dist=;
for(int i=;i<n;i++) dist+=DistanceToLine(p[i],Line(p1,p2-p1));
if(dist<mini) mini=dist;
}
printf("Case #%d: %.3lf\n",kase,mini/(1.0*n));
}
}
PS.为保证跟前面的计算几何模板一致性,就把整个模板都copy了。
UVA 11168 - Airport - [凸包基础题]的更多相关文章
- UVA 11168 Airport(凸包)
Airport [题目链接]Airport [题目类型]凸包 &题解: 蓝书274页,要想到解析几何来降低复杂度,还用到点到直线的距离公式,之后向想到预处理x,y坐标之和,就可以O(1)查到距 ...
- UVA 11168 Airport(凸包+直线方程)
题意:给你n[1,10000]个点,求出一条直线,让所有的点都在都在直线的一侧并且到直线的距离总和最小,输出最小平均值(最小值除以点数) 题解:根据题意可以知道任意角度画一条直线(所有点都在一边),然 ...
- 简单几何(数学公式+凸包) UVA 11168 Airport
题目传送门 题意:找一条直线,使得其余的点都在直线的同一侧,而且使得到直线的平均距离最短. 分析:训练指南P274,先求凸包,如果每条边都算一边的话,是O (n ^ 2),然而根据公式知直线一般式为A ...
- uva 11168 - Airport
凸包+一点直线的知识: #include <cstdio> #include <cmath> #include <cstring> #include <alg ...
- UVa 11168(凸包、直线一般式)
要点 找凸包上的线很显然 但每条线所有点都求一遍显然不可行,优化方法是:所有点都在一侧所以可以使用直线一般式的距离公式\(\frac{|A* \sum{x}+B* \sum{y}+C*n|}{\sqr ...
- Android测试基础题(三)
今天接着给大家带来的是Android测试基础题(三). 需求:定义一个排序的方法,根据用户传入的double类型数组进行排序,并返回排序后的数组 俗话说的好:温故而知新,可以为师矣 packag ...
- 小试牛刀3之JavaScript基础题
JavaScript基础题 1.让用户输入两个数字,然后输出相加的结果. *prompt() 方法用于显示可提示用户进行输入的对话框. 语法: prompt(text,defaultText) 说明: ...
- 小试牛刀2:JavaScript基础题
JavaScript基础题 1.网页中有个字符串“我有一个梦想”,使用JavaScript获取该字符串的长度,同时输出字符串最后两个字. 答案: <!DOCTYPE html PUBLIC &q ...
- UVa 1339 Ancient Cipher --- 水题
UVa 1339 题目大意:给定两个长度相同且不超过100个字符的字符串,判断能否把其中一个字符串重排后,然后对26个字母一一做一个映射,使得两个字符串相同 解题思路:字母可以重排,那么次序便不重要, ...
随机推荐
- AndroidManifest详解
一,重要性AndroidManifest.xml是Android应用程序中最重要的文件之一.它是Android程序的全局配置文件,是每个 android程序中必须的文件.它位于我们开发的应用程序的根目 ...
- 使用srvany.exe把程序安装成windows服务的方法
http://mazhihui.iteye.com/blog/1294431 srvany.exe是什么? srvany.exe是Microsoft Windows Resource Kits工具集的 ...
- Eclipse Maven 配置setting.xml 的镜像远程仓库
1.在.m2中新建settings.xml文件 1.window-->Preferences-->Maven-->User Settings 3.点击open file 编辑将远程仓 ...
- samba 服务器
1.apt-get install smaba 2.安装完成后apt-get install smbclient 然后就是配置那个.conf文件,这个到网上搜下ubuntu下配置smaba服务器就可以 ...
- Java API方式调用Kafka各种协议
众所周知,Kafka自己实现了一套二进制协议(binary protocol)用于各种功能的实现,比如发送消息,获取消息,提交位移以及创建topic等.具体协议规范参见:Kafka协议 这套协议的具 ...
- 使用jsp实现文件上传的功能
首先是表单的jsp文件:upload.jsp <%@ page contentType="text/html;charset=UTF-8" language="ja ...
- Swift - 可选类型详解
可选类型详解 直接上代码解释 // 类中所有的属性在对象初始化时,必须有初始化值 class Person : NSObject { var name : String? var view : UIV ...
- Cufon在渲染网页字体你不知道的事
清单 1. 无效的 font-family 字体指定 <style> .introduction { font-family:'Baroque Script';} </style&g ...
- 《转载》Python3安装Scrapy
运行平台:Windows Python版本:Python3.x IDE:Sublime text3 转载自:http://blog.csdn.net/c406495762/article/detail ...
- iptables 指令语法
iptables 指令 语法: iptables [-t table] command [match] [-j target/jump] -t 参数用来指定规则表,内建的规则表有三个,分别是:nat. ...