UVA 1475 Jungle Outpost(二分+半平面交)
来源:互联网 发布:mac mini 不更新 编辑:程序博客网 时间:2024/05/29 12:04
UVA 1475 Jungle Outpost(二分+半平面交)
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4221
题意:
在丛林中有n个瞭望台,形参了一个凸n多边形.这些瞭望台的保护范围就是这个凸多边形内的任意点. 敌人进攻时,会炸掉一些瞭望台,使得总部暴露在那些剩下的瞭望台的凸包之外.你的任务是选一个点作为总部,使得敌人需要炸坏的瞭望台数目尽量多. n个瞭望台按顺时针顺序输入.
分析:刘汝佳<<训练指南>> P281例题12
如果敌人只有一颗炸弹,炸掉一个顶点后,不会暴露在外面的是一条有向直线的”左边”. 每条直线代表一个半平面,这样所有的这种直线就形成了一个半平面交. 我们就要看这个交集是否是非空的了.
如果敌人有多个炸弹,他应该怎么炸才是最优呢? 这多个炸弹肯定是炸毁连续的几个顶点才最好.(自己画图比较一下) 所以这些炸弹又形成了一个行的半平面,我们依然看所有半平面是否存在交集即可.
如果存在交集,说明敌人炸弹不够,还要炸更多的瞭望台才能使得我们在任何地方建立总部都会被暴露.
所以我们二分敌人炸弹的数目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 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;}//得到a与b两直线的交点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;}//返回半平面交的凸多边形poly节点集合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]; if(fabs(Cross(q[last].v,q[last-1].v))<eps) { last--; if(OnLeft(q[last],L[i].p)) q[last]=L[i]; } if(first<last) p[last-1]=GetIntersection(q[last-1],q[last]); } 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=50000+5;Point p[maxn],poly[maxn];Line L[maxn];int main(){ int n; while(scanf("%d",&n)==1) { for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); if(n==3)//三角形的话,直接删除一个点即可 { printf("1\n"); continue; } reverse(p,p+n);//将所有顶点逆时针存放 //当炸掉n-2个连续的点时,半平面交肯定是空 int left=1,right=n-2; while(right>left) { int mid=left+(right-left)/2; for(int i=0;i<n;i++) L[i]=Line(p[i],p[(i+1+mid)%n]-p[i]); int m=HalfplaneIntersection(L,n,poly); //m>0表示半平面交非空,那么需要加炸弹 if(m>0) left=mid+1; else right=mid; } printf("%d\n",left); } return 0;}
0 0
- UVA 1475 Jungle Outpost(二分+半平面交)
- UVA 1475 - Jungle Outpost(二分 + 半平面交)
- POJ 3968|UVALive 4992|HDU 3761|UVA 1475|Jungle Outpost|二分|半平面交
- HDU 3761 Jungle Outpost(二分+半平面交)
- LA 4492 Jungle Outpost 半平面交,二分答案
- 【二分+半平面交】 HDOJ 3761 Jungle Outpost
- uva 1475 - Jungle Outpost(二分+平面相交)
- LA4992 Jungle Outpost 半平面交
- LA 4992 Jungle Outpost 半平面交 -
- UVA LA3890 二分和半平面交
- poj3525 二分+半平面交
- UVA LA2797 二分加半平面交,很巧妙的二分
- poj 3525 二分+半平面交
- POJ3525(二分+半平面交)
- POJ 3525 二分+半平面交
- uvalive 4992(半平面交+二分)
- UVALive 3890 (半平面交 二分)
- HDU 3761 (二分 半平面交)
- 2015腾讯校园招聘(菜鸟逆袭腾讯,offer get)
- 模拟赛 肥得更高
- java中的基本数据类型与封装类
- A + B Problem II
- SQL server2014 sql语句
- UVA 1475 Jungle Outpost(二分+半平面交)
- 模拟赛 警察叔叔就是这个人!
- 产生任意随机数发生器
- OAuth的机制原理讲解
- 取硬币问题最优策略
- leetcode :Find Minimum in Rotated Sorted Array
- using thymeleaf之一thymeleaf认识
- Winpcap网络编程八之Winpcap学习教程,发包,发包!
- FZU 2086 餐厅点餐(枚举)