UVA 11168 Airport(凸包+直线两点式转一般式)
题意:
平面上有n个点,你要找一条直线,使得所有点都是直线的同一侧(可以在直线上),且所有点到直线的距离和最小. 问你所有点到直线的距离和最小是多少(要求输出平均值)?
分析: 刘汝佳<<训练指南>>P274 例题7
首先如果存在这样的直线,那么该直线肯定是点集凸包的某一条边.(可以画图验证一下,与凸包相离的直线肯定不考虑,与凸包相交1点的直线可以通过旋转来继续缩短所有点到直线的距离和)
由于凸包最多有n条边,所以我们需要一次求出所有点到这n条边的距离和. 点到直线的距离这里我们用解析几何的方式来算:
点(x0,y0)到直线Ax+By+C=0的距离= |Ax0+By0+C|/sqrt(A*A+B*B)
要求n个点的距离,就是上面的n个式子相加,由于所有点在直线同侧,所以我们可以先不考虑绝对值,直接求和,最后再求绝对值,所以最终结果为(x_all和y_all为所有点的x与y坐标之和):
fabs(A*x_all+B*y_all+n*C)/sqrt(A*A+B*B)
之后我们只要对比n个值找出最小的即可.
最后还有一个问题:已知直线的两点坐标(x1,y1)与(x2,y2)如何得到直线的 Ax+By+C=0的方程? 假设直线上的点为(x,y),由斜率相同可得公式: (y-y1)/(x-x1)=(y2-y1)/(x2-x1) ,化简可得 (y-y1)*(x2-x1)=(x-x1)*(y2-y1), 化简可得 (y2-y1)*x-(x2-x1)*y+y1(x2-x1)-x1(y2-y1)=0.对比可知:
A=(y2-y1) B=-(x2-x1) C=y1(x2-x1)-x1(y2-y1)=-y1*B-x1*A
注意当整个点集的凸包退化成一条线段时,总距离==0.
AC代码:
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
const double eps=1e-10;
int dcmp(double x)
{
if(fabs(x)<eps) return 0;
return x<0?-1:1;
}
struct Point
{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
bool operator==(const Point& B)const
{
return dcmp(x-B.x)==0 && dcmp(y-B.y)==0;
}
bool operator<(const Point &B)const
{
return dcmp(x-B.x)<0 || (dcmp(x-B.x)==0 && dcmp(y-B.y)<0);
}
};
typedef Point Vector;
Vector operator-(Point A,Point B)
{
return Vector(A.x-B.x,A.y-B.y);
}
double Cross(Vector A,Vector B)
{
return A.x*B.y-A.y*B.x;
}
int ConvexHull(Point *p,int n,Point *ch)
{
sort(p,p+n);
n=unique(p,p+n)-p;
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;
}
/***以上为刘汝佳模板***/
void get_line(Point p1,Point p2,double &a,double &b,double &c)
{
a=p2.y-p1.y;
b=p1.x-p2.x;
c=-p1.y*b-p1.x*a;
}
const int maxn=10000+5;
Point p[maxn],q[maxn];
int main()
{
int T; scanf("%d",&T);
for(int kase=1;kase<=T;kase++)
{
int n;
double x_all=0,y_all=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
x_all+=p[i].x;
y_all+=p[i].y;
}
int m=ConvexHull(p,n,q);
if(m<=2)//注意这里不是 m==2
{
printf("Case #%d: 0.000\n",kase);
continue;
}
double ans=1e10;//最小距离
for(int i=0;i<m;++i)
{
double a,b,c;
get_line(q[i],q[(i+1)%m],a,b,c);
ans=min(ans, fabs(a*x_all+b*y_all+n*c)/sqrt(a*a+b*b));
}
printf("Case #%d: %.3lf\n",kase,ans/n);
}
return 0;
}
分享到:
相关推荐
5. **验证功能**:为了确保构建出的凸包包含了所有输入点,还需要实现一个验证函数`have`,检查所有点是否都位于最终的凸包内部或边界上。 ### 总结 通过对UVA109题目的解析可以看出,凸包构建是一个典型的计算...
快速Hull算法的核心思想是分治,通过选取两个最远的点作为超平面的边界,将其他点分为两部分:位于一边的点肯定在最终凸包的同一侧,另一边的点则需要递归处理。每次选择距离当前边界最近的点,构建新的超平面,直到...
zoj上凸包题目,可用作模板,相信您用了之后一定不会后悔的
然后可以递归的从内向外扩展凸包,在当前直线的2侧寻找最高点,最高点肯定在凸包中,这里涉及到一些数学知识: a,首先定义射线p1到p2的左侧:若p1 p2 p构成的顺序是逆时针,称p在射线的左侧 b,三角形p1 p2 p3的...
凸包是由点集中所有点构成的多边形,使得任何从多边形外部到内部的直线段都会穿过多边形的边界。在给定的描述中,提到的方法比传统的“快包”方法(如Jarvis March或Graham's Scan)速度更快,尽管可能不够完美,但...
在这个场景中,"凸包算法计算随机散点的最小凸包"就是寻找这些散乱分布的点构成的最小包围区域。 描述中提到的程序可能是一个用C++编写的示例,因为它提到了需要Visual Studio 2012或更高版本来运行。VS2012及以上...
给定一组二维或三维空间中的点,凸包是这些点构成的多边形或多面体,使得任何从多边形外部到内部的直线都会穿过至少一个点。在二维空间中,我们可以直观地想象它是一个“橡皮筋”围绕这些点最外层形成的封闭形状。 ...
1. 首先,计算点 p 到凸包上每个面的距离,如果所有距离都大于 0,则点 p 在凸包外部。 2. 如果点 p 到凸包上某个面的距离等于 0,则点 p 在凸包表面上。 3. 如果点 p 到凸包上所有面的距离都小于 0,则点 p 在凸包...
凸包问题(包含蛮力算法和快速凸包算法两种解法)+最优二叉查找树,并且都利用javafx生成可视化界面,开箱即用,代码含注释,原理通俗易懂。
凸包是计算机图形学中的一个重要概念,它指的是在一组点集中,由这些点构成的最小边界多边形,这个多边形所有的顶点都是原始点集中的点。 【描述】中提到的压缩包内容主要包括以下几个部分: 1. **窗体工程文件...
在计算几何中,"凸包"是一个核心概念,用于描述一个几何对象(如点集)所能形成的最外层边界,使得任何从这个边界外部到内部的直线段都会穿过凸包的边界。这个边界本身就是一个凸多边形,即所有的内角都不超过180度...
一个凸包可以被定义为一个封闭的二维形状,其中任何从该形状外部到内部的直线段都会穿过形状的边界。在二维空间中,一个点集的凸包是包含这些点的最小的凸多边形。这个过程在很多应用中都有用到,例如碰撞检测、图形...
火焰的凸包检测,视频放到了根目录下,记得改一下目录。...我们使用凸包计算火灾区域边界的无序性,凸包就是给定二维平面上的点集,将最外层的点连接起来构成的凸多边形,凸包是能包含点集中所有点。
在给定的“编写的凸包算法”项目中,我们可以看到它是由C++语言实现的,专注于处理任意数量的点,并且提供了用户友好的界面,包括“凸包生成”和“清理画布”两个功能。 首先,我们来理解一下凸包的基本概念。在二...
具体来说,对于每一条可能的边,如果这条边两侧的点在同一直线上的投影方向不同(即一部分点位于直线的一侧,另一部分点位于直线的另一侧),那么这条边就不属于凸包边界;反之,则认为这条边可能是凸包的一部分。...
一种更高效的方法是找到凸包上的两个最远端点,这可以通过在构建凸包的过程中维护最大距离信息来实现。 在VC++环境下,可以利用标准库或第三方库(如CGAL - Computational Geometry Algorithm Library)来实现这些...
从一个极点开始,按顺序检查其他点,找到离当前点最近的点并加入凸包,然后以新加入的点为极点,继续寻找下一个最近的点,直到所有点都被考虑过。 5. **代码实现**:在Java中,你可以创建一个类来表示点,然后使用 ...
接着,我们可以编写一个函数来比较两个点的顺序,通常是以逆时针方向排序,这是构建凸包的关键步骤。这个函数可以根据极角排序原则实现: ```c int comparePoints(const void *a, const void *b) { Point *p1 = ...
凸包可以被定义为一个包含所有点的最小凸多边形,即在这个多边形内部,任何两点的线段都完全位于多边形内。在给定的Java程序中,“计算几何求凸包算法的java实现”是解决这个问题的关键。 这个Java代码实现了对离散...
4. **扫描并更新**:对于剩余的每个点,如果它与凸包上最后两个点形成的向量在基准点和凸包最后一个点的向量之上,那么就将该点添加到凸包中,并移除凸包中的最后一个点,直到凸包再次变得“凸”。 5. **完成**:当...