HDU1348 Wall 【简单凸包】
来源:互联网 发布:sap erp 知乎 编辑:程序博客网 时间:2024/05/19 12:15
【题目大意】
首先读入N,L分别表示有N座城堡以及城墙到城堡的最近距离不得低于L
然后N行输入每个城堡的平面坐标
需要求出最短的能够满足条件的城墙长度。
条件:
1)城墙到城堡的最近距离不得低于L
2)城墙必须包含最外圈的所有城堡
输入包含多组数据
保留0位小数输出
【解题思路】
该题是典型的凸包问题
在此简单介绍一下凸包:
凸包(Convex Hull)是一个计算几何(图形学)中的概念。
在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。
X的凸包可以用X内所有点(X1,...Xn)的线性组合来构造.
在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。
用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有的点。
笔者求解凸包常用Andrew算法(Granham算法的变种),稳定性较好
【Andrew算法】
int ConvexHull(Point *P,int n,Point *Q){//返回凸包顶点个数,P为读入的点集,n为点集数量,Q为凸包数组 sort(P,P+n); int m=0; for (int i=0;i<n;++i){ while (m>1&&(Cross(Q[m-1]-Q[m-2],P[i]-Q[m-2])<=0)) m--; Q[m++]=P[i];}int k=m;for (int i=n-2;i>=0;--i){while (m>k&&(Cross(Q[m-1]-Q[m-2],P[i]-Q[m-2])<=0)) m--;Q[m++]=P[i];}if (n>1) m--;return m;}
double Cross(Vector A,Vector B){//叉积return A.x*B.y-A.y*B.x;}
了解了凸包之后,本题就可以快速解决了。
不用理会L,只需要在最后加上2*PI*L(这是因为所有城堡外围所对应的圆心角之和为凸包对应多边形的外角和,即2PI弧度)
【代码】
#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>#include<cmath>#include<ctime>#include<cstring>#include<string>#include<cctype>#include<iomanip>#include<vector>#define LL long long#define UI unsigned int//#define LOCALusing namespace std;struct Point{ double x,y; Point(double x=0,double y=0):x(x),y(y){}};typedef Point Vector;const double eps=1e-10;const double PI=acos(-1.0);Vector operator + (Vector A,Vector B){return Vector(A.x+B.x,A.y+B.y);}Vector operator - (Point A,Point B){return Vector(A.x-B.x,A.y-B.y);}Vector operator * (Vector A,double p){return Vector(A.x*p,A.y*p);}Vector operator / (Vector A,double p){return Vector(A.x/p,A.y/p);}bool operator < (const Point &A,const Point &B){return A.x<B.x || (A.x==B.x&&A.y<B.y);}int Vector_Compare(double x){return (x<eps) ? 0 : (x<0 ? -1 : 1);}bool operator == (const Point &A,const Point &B){return Vector_Compare(A.x-B.x)==0&&Vector_Compare(A.y-B.y);}double Dot(Vector A,Vector B){return A.x*B.x+A.y*B.y;}double Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}double Length(Vector A){return sqrt(Dot(A,A));}double PolgonRound(Point *Q,int n){double round=0;for (int i=0;i<n-1;++i) round+=Length(Q[i+1]-Q[i]);round+=Length(Q[0]-Q[n-1]);return round;}int ConvexHull(Point *P,int n,Point *Q){ sort(P,P+n); int m=0; for (int i=0;i<n;++i){ while (m>1&&(Cross(Q[m-1]-Q[m-2],P[i]-Q[m-2])<=0)) m--; Q[m++]=P[i];}int k=m;for (int i=n-2;i>=0;--i){while (m>k&&(Cross(Q[m-1]-Q[m-2],P[i]-Q[m-2])<=0)) m--;Q[m++]=P[i];}if (n>1) m--;return m;}const int N=1011;int T;int n,L;Point P[N],Q[N];int main(){#ifdef LOCAL freopen("HDU1348.in","r",stdin);#endif scanf("%d",&T); while (T--){ double ans=0; int opt=0; scanf("%d%d",&n,&L); for (int i=0;i<n;++i){ scanf("%lf%lf",&P[i].x,&P[i].y);}int num=ConvexHull(P,n,Q);ans=PolgonRound(Q,num);ans+=2*PI*L;if (T!=0) printf("%.0lf\n\n",ans);//注意本题的格式,有坑else printf("%.0lf\n",ans);}return 0;}
【总结】
凸包求法以及多边形外角和的巧妙处理
2 0
- HDU1348 Wall 【简单凸包】
- hdu1348 Wall 凸包
- HDU1348 Wall 凸包
- hdu1348 Wall(凸包)
- Wall(HDU1348,凸包周长)
- hdu1348 Wall(凸包模板题)
- hdu1348 Wall
- 凸包,模板---hdu1348
- 【计算几何初步-凸包-Graham扫描法-极角序】【HDU1348】 WALL
- POJ1113 wall 简单凸包
- hdu1348 Wall (求凸包周长)
- HDU1348-Walls(经典凸包)
- hdu1348 练习凸包模板使用
- poj 1113 wall 简单的凸包
- 【凸包】Wall
- POJ1113 Wall 凸包
- Wall 凸包
- poj1113--Wall(凸包)
- Js_限制上传文件类型
- ubuntu更换源
- Linux_10 Useful du (Disk Usage) Commands to Find Disk Usage of Files and Dir
- Mac 不显示任何来源选项
- Js_window.setInterval & window.setTimeout
- HDU1348 Wall 【简单凸包】
- MQTT服务器搭建--Mosquitto用户名密码配置
- META http-equiv 大全
- Android 应用间共享文件(FileProvider)
- Java重点学习笔记
- Js_如何判断 null
- android studio 移植的bug解决记录
- Struts FileUpload
- Js_$符号