UVA 1396 Most Distant Point from the Sea(二分+半平面交)
来源:互联网 发布:淘宝极速退款条件 编辑:程序博客网 时间:2024/05/24 02:08
UVA 1396 Most Distant Point from the Sea(二分+半平面交)
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4142
题意:
有一个凸多边形的海岛,要你求出海岛上离海最远的点,输出它的距离. 海岛的每个节点按逆时针顺序给出.
分析: 刘汝佳<<训练指南>>P279例题10
我们二分最远距离mid,看看是否存在离海的距离>=mid的点即可.
如何判断到底是否存在这样的点呢? 把凸多边形的每条边往多边形内部平行移动mid距离, 这样所有的新边构成了一个新的区域. 如果这个区域不空,那么就说明肯定存在离海距离>=mid 的点的.
如何求出上图的红色区域呢? 就要用到半平面交了,每条红色的边代表一个半平面(指该直线左边的区域).将原始边往它的法向量平移mid距离就得到了新的边.
AC代码:
#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>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){}};//向量typedef Point Vector;//点-点==向量Vector operator-(Point A,Point B){ return Vector(A.x-B.x,A.y-B.y);}//向量+向量==向量 或 点+向量==点Vector operator+(Vector A,Vector 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);}//求向量长度double Length(Vector v){ return sqrt(v.x*v.x+v.y*v.y);}//返回v逆时针旋转90度的单位向量Vector Normal(Vector v){ double L=Length(v); return Vector(-v.y/L, v.x/L);}//叉积double Cross(Vector A,Vector B){ return A.x*B.y-A.y*B.x;}//直线struct Line{ Point p; Vector v; double ang; Line(){} Line(Point p,Vector v):p(p),v(v) { ang=atan2(v.y,v.x); } bool operator<(const Line &L)const { return ang<L.ang; }};//判断p是否在直线L左边(在直线上不算)bool OnLeft(Line L,Point p){ return Cross(L.v,p-L.p)>0;}//得到直线的交点Point GetIntersection(Line a,Line b){ Vector u=a.p-b.p; double t=Cross(b.v,u)/Cross(a.v,b.v); return a.p+a.v*t;}//求直线集合L构成的半平面交集,如果存在是一个凸包int HalfplaneIntersection(Line *L,int n,Point *poly){ //极角排序 sort(L,L+n); int first=0,last=0; Point *p=new Point[n]; Line *q=new Line[n]; q[0]=L[0]; for(int i=1;i<n;i++) { //删除尾部无效节点 while(first<last && !OnLeft(L[i],p[last-1])) last--; //删除头部无效节点 while(first<last && !OnLeft(L[i],p[first])) first++; //插入新直线 q[++last]=L[i]; //如果新插入的直线与last直线平行,需要删除最右边的那条 if(fabs(Cross(q[last].v,q[last-1].v))<eps) { last--; if(OnLeft(q[last],L[i].p)) q[last]=L[i]; } //新插入直线与上一条直线构成last-1交点 if(first<last) p[last-1]=GetIntersection(q[last-1],q[last]); } //同first直线排序尾部无效节点 while(first<last && !OnLeft(q[first],p[last-1])) last--; //半平面不构成有界区域 if(last-first<=1 ) return 0; //求首直线与尾直线交点 p[last]=GetIntersection(q[last],q[first]); int m=0; for(int i=first;i<=last;i++) poly[m++]=p[i]; return m;}const int maxn=100+5;Point p[maxn],poly[maxn];Vector v1[maxn],v2[maxn];Line L[maxn];int main(){ int n; while(scanf("%d",&n)==1 && n) { for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); for(int i=0;i<n;i++) { v1[i]=p[(i+1)%n]-p[i]; v2[i]=Normal(v1[i]);//v2是v1逆时针转90度后的单位法向量 } //二分求距离 double left=0,right=1e8; while(right-left>1e-6) { double mid=(left+right)/2; for(int i=0;i<n;i++) L[i]=Line(p[i]+v2[i]*mid,v1[i]); int m=HalfplaneIntersection(L,n,poly); if(!m) right=mid; else left=mid; } printf("%.6lf\n",left); } return 0;}
0 0
- UVA 1396 Most Distant Point from the Sea(二分+半平面交)
- UVA 1396 - Most Distant Point from the Sea(二分+半平面交)
- POJ3525 Most Distant Point from the Sea(半平面交)
- POJ 3525 Most Distant Point from the Sea(半平面交+二分)
- Poj 3525 Most Distant Point from the Sea (二分+半平面求交)
- POJ 3525 Most Distant Point from the Sea 半平面交 +二分
- poj 3525 Most Distant Point from the Sea(半平面交+二分)
- POJ 3525 Most Distant Point from the Sea 二分+半平面交
- poj 3525 Most Distant Point from the Sea(半平面交+二分内推进)
- POJ 3525 Most Distant Point from the Sea 二分+半平面交
- LA3890 Most Distant Point from the Sea 二分+半平面交
- poj 3525 Most Distant Point from the Sea 半平面交 + 二分
- poj 3525 Most Distant Point from the Sea,半平面交 + 二分
- 【二分+半平面交】 POJ 3525 Most Distant Point from the Sea
- POJ3525-Most Distant Point from the Sea(二分+半平面交)
- POJ 3525 Most Distant Point from the Sea 二分+半平面交
- POJ 3525 Most Distant Point from the Sea 二分+内推+半平面交
- POJ 3525 Most Distant Point from the Sea 半平面交+二分
- POJ1087 A Plug for UNIX 【最大流】
- 如何保持百度首页的关键字排名
- JavaScript编码规范
- Zoj 3471 Most Powerful 状态压缩
- PAT(A) 1013
- UVA 1396 Most Distant Point from the Sea(二分+半平面交)
- 算法题: 8进制用法——没有2,4的数列
- iptables命令小结
- 单向链表
- Java基础之继承意义
- 黑马程序员-day03java基础语言组成2
- 作用域与函数传值调用
- printf()
- EL