您的位置:首页 > 其它

半平面交入门 poj 3335 poj 1474 poj 1279 半平面交模板

2012-03-30 23:09 471 查看
今天学了学半平面交,其实很简单的,我说的是最原始的思想,复杂度是O(n^2)的

相当于中学的时候学的线性规划,用n条直线去切割一个平面,每条直线代表一定的限制,最后如果有解就会在中间留下一个凸核

这个凸核中的点就是满足所有的约束条件的解集

典型的例子 :给你一个多边形,判断多边形内是否存在一个点,从这个点可以看到多边形周围所有的点

做法:

多边形的每条边都是一个约束条件,边的顺序为顺时针

用每条边的直线去切割当前平面:枚举平面点集中的点,假如当前点(p)在核外,

判断p-1与p+1是不是在核内,如果是,则肯定有交点

分别把求出的交点加入点集

不断重复的做下去

最后点集中的点就是要求的的可行解

下面是我的模板,自己看了别人的而博客后调了好久终于才搞定的,还算简洁

const  int maxn = 20000;
const double eps = 1e-8;
inline double sgn(double x) {return fabs(x)<eps?0:(x>0?1:-1);}
struct Point{
double x,y;
Point(double tx=0,double ty=0){x=tx;y=ty;}
bool operator == (const Point& t) const {
return sgn(x-t.x)==0 && sgn(y-t.y)==0;
}
}p[maxn],st[maxn],pp[maxn];
struct Seg{Point s,e;};
double cross(Point a,Point b,Point c){return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);}
bool outside(Seg seg,Point p){return cross(seg.s,seg.e,p)>eps;}//strictly outside the ploygon
bool inside(Seg seg,Point p){return cross(seg.s,seg.e,p)<-eps;}//strictly inside the ploygon
Point Intersect(Point p1, Point p2, Point p3, Point p4) {
double a1, b1, c1, a2, b2, c2, d;Point p;
a1 = p1.y - p2.y; b1 = p2.x - p1.x; c1 = p1.x*p2.y - p2.x*p1.y;
a2 = p3.y - p4.y; b2 = p4.x - p3.x; c2 = p3.x*p4.y - p4.x*p3.y;
d = a1*b2 - a2*b1;
if ( fabs(d) < eps )    return false;
p.x = (-c1*b2 + c2*b1) / d;
p.y = (-a1*c2 + a2*c1) / d;
return p;
}
int n,ban_tot;
void CUT(Seg seg){
int i,tot=0;
for(i=1;i<=ban_tot;i++){
if(!outside(seg,p[i]))  pp[++tot]=p[i];//p[i] :inside or on the boundary
else {//p[i]: must be outside
if(inside(seg,p[i-1]))     pp[++tot]=Intersect(seg.s,seg.e,p[i],p[i-1]);//p[i-1] must be inside
if(inside(seg,p[i+1]))     pp[++tot]=Intersect(seg.s,seg.e,p[i],p[i+1]);//p[i+1] must be inside
}
}ban_tot=tot;
pp[tot+1]=pp[1];pp[0]=pp[tot];
memcpy(p,pp,sizeof(pp));
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: