BZOJ 1137 半平面交

半平面交的板子

//By SiriusRen
#include <bits/stdc++.h>
#define double long double
using namespace std;
const int N=100050;
const double eps=1e-10;
int n,m,xx,yy,tot;
double Ans;
vector<int>vec[N];
struct Point{double x,y;}point[N];
struct Line{Point a,b;double angle;}line[N],q[N];
void addline(Line &l,Point a,Point b){
    l.a=a,l.b=b,l.angle=atan2(b.y-a.y,b.x-a.x);
}
Point operator-(Point a,Point b){
    Point c;c.x=a.x-b.x,c.y=a.y-b.y;return c;
}
double operator*(Point a,Point b){
    return a.x*b.y-a.y*b.x;
}
bool operator<(Line a,Line b){
    if(a.angle==b.angle)return (b.b-a.a)*(b.a-a.a)>0;
    return a.angle<b.angle;
}
Point inter(Line a,Line b){
    double k1,k2,t;
    k1=(a.b-b.a)*(b.b-b.a);
    k2=(b.b-b.a)*(a.a-b.a);
    t=k1/(k1+k2);
    Point ans;
    ans.x=a.b.x+(a.a.x-a.b.x)*t;
    ans.y=a.b.y+(a.a.y-a.b.y)*t;
    return ans;
}
double dis(Point x,Point y){
    x=y-x;
    return sqrt(x.x*x.x+x.y*x.y);
}
bool judge(Line a,Line b,Line t){
    Point p=inter(a,b);
    return (t.a-p)*(t.b-p)<0;
}
void bpmj(){
    sort(line+1,line+1+tot);
    n=0;
    for(int i=1;i<=tot;i++){
        if(abs(line[i].angle-line[i-1].angle)>eps)n++;
        line[n]=line[i];
    }
    int r=1,l=0;
    q[0]=line[1],q[1]=line[2];
    for(int i=3;i<=n;i++){
        while(l<r&&judge(q[r],q[r-1],line[i]))r--;
        while(l<r&&judge(q[l],q[l+1],line[i]))l++;
        q[++r]=line[i];
    }
    while(l<r&&judge(q[r],q[r-1],q[l]))r--;
    while(l<r&&judge(q[l],q[l+1],q[r]))l++;
    q[r+1]=q[l],tot=0;
    for(int i=l;i<=r;i++)point[++tot]=inter(q[i],q[i+1]);
    point[++tot]=point[1];
    for(int i=1;i<tot;i++)Ans+=dis(point[i],point[i+1]);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%Lf%Lf",&point[i].x,&point[i].y);
    Ans=-dis(point[1],point[n]);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&xx,&yy);
        if(xx>yy)swap(xx,yy);
        vec[xx].push_back(yy);
    }
    for(int i=1,j,k;i<=n;i++){
        sort(vec[i].begin(),vec[i].end());
        for(j=n,k=vec[i].size()-1;j>i&&~k;j--,k--)
            if(vec[i][k]!=j)break;
        if(i==1&&j==n){printf("%.10Lf\n",dis(point[1],point[n]));return 0;}
        if(j>i)addline(line[++tot],point[j],point[i]);
    }addline(line[++tot],point[1],point[n]);
    bpmj();
    printf("%.10Lf\n",Ans);
}
时间: 2024-10-12 11:29:25

BZOJ 1137 半平面交的相关文章

BZOJ 1137: [POI2009]Wsp 岛屿 半平面交

1137: [POI2009]Wsp 岛屿 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 165  Solved: 78[Submit][Status][Discuss] Description Byteotia岛屿是一个凸多边形.城市全都在海岸上.按顺时针编号1到n.任意两个城市之间都有一条笔直的道路相连.道路相交处可以自由穿行.有一些道路被游击队控制了,不能走,但是可以经过这条道路与未被控制的道路的交点.问

BZOJ 1038 ZJOI 2008 瞭望塔 半平面交

题目大意:给出一个村庄的轮廓,在这个村庄里可以在随意的地方建一个瞭望塔.这个塔须要足够高,使得可以看得村庄的全貌. 求这个瞭望塔的最小高度. 思路:对于村庄中的每一条边,瞭望塔为了看见它.必需要在这个直线左側的半平面区域.这种话为了满足全部的边的需求,做一次半平面交,瞭望塔的最高点必须在全部边的半平面交的区域内. 例如以下图例子. 全部边的半平面交区域就是上面的图形.设上面半平面的函数关系是F(x).村长的函数关系是G(x),那么问题就转化成了求一个x,使得(F(x) - G(x))最小. 这个

HDU 2297 半平面交

Run Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 640    Accepted Submission(s): 181 Problem Description Since members of Wuhan University ACM Team are lack of exercise, they plan to particip

关于半平面交

嗯,这是一个很屌的东西.可以把他想象成数学中的线性规划问题,然后自然而然得想到就可以求最优解啦. 如何求解半平面交????? 做法一:暴力枚举点,用该点切割现有的凸多边形,这样的复杂度是O(n^2) 做法二:神奇的分治O(nlogn),然而我并不会.... 做法三:参见2006年朱泽园大神发明的排序增量法:这里就暂时不给详细介绍了. 复杂度O(nlogn),如果把快速排序改成基数排序,复杂度可以进一步降为:O(n)!!!!!! 半平面交的另外一个应用是求多边形的核:可以想象成站在一个多边形的点上

计算几何 半平面交

LA 4992 && hdu 3761 Jungle Outpost 杭电的有点坑啊..一直爆内存,后来发现大白的半平面交模板那里 point *p = new point[n]; line *q = new line[n]这里出了问题,应该是在函数里面申请不了比较大的数组,所以爆内存..我在全局定义了两个数组就不会爆了.. 本来跑了17s多的,后来半平面交sort( l, l + n ) 被我注释了,就跑了9s多,LA上跑了 2s..应该是输入数据比较好,不用按照极角排序..然后就是照着

POJ3525 半平面交

题意:求某凸多边形内部离边界最远的点到边界的距离 首先介绍半平面.半平面交的概念: 半平面:对于一条有向直线,它的方向的左手侧就是它所划定的半平面范围.如图所示: 半平面交:多个半平面的交集.有点类似二元函数的线性规划.如图 求半平面交:用的kuangbin模板= = sol:二分答案 二分距离值,按这个值把边界向内缩,再求新的半平面交.如图: 绿色的是原图形,蓝色是按距离值向里面缩进去之后得到的新图形.对这个新图做半平面交即可. 若半平面交存在,说明与边界的距离是该值的点存在(半平面交里面的点

bzoj2618[Cqoi2006]凸多边形 半平面交

这是一道半平面交的裸题,第一次写半平面交,就说一说我对半平面交的理解吧. 所谓半平面交,就是求一大堆二元一次不等式的交集,而每个二元一次不等式的解集都可以看成是在一条直线的上方或下方,联系直线的标准方程就可以得出.于是乎这些不等式就可以转化为一些半平面,求的就是半平面交. 而半平面交不可能交出凹多边形(因为凹多边形的定义是有一条边所在的直线能把该多边形分成若干块...YY一下就知道这是不可能的),这是一个十分优美的性质,正类似于凸包(写法也是有些相似的),但半平面交可能交出无界,于是可以加四条类

poj3335 半平面交

题意:给出一多边形.判断多边形是否存在一点,使得多边形边界上的所有点都能看见该点. sol:在纸上随手画画就可以找出规律:按逆时针顺序连接所有点.然后找出这些line的半平面交. 题中给出的点已经按顺时针排好序了,所以只要倒过来一下就可以了.很简单的模板题. 1 #include<vector> 2 #include<list> 3 #include<map> 4 #include<set> 5 #include<deque> 6 #includ

【bzoj2618】[Cqoi2006]凸多边形 半平面交

题目描述 逆时针给出n个凸多边形的顶点坐标,求它们交的面积.例如n=2时,两个凸多边形如下图: 则相交部分的面积为5.233. 输入 第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形.第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标. 输出 输出文件仅包含一个实数,表示相交部分的面积,保留三位小数. 样例输入 2 6 -2 0 -1 -2 1 -2 2 0 1 2 -1 2 4 0 -3 1 -1 2 2 -1 0 样例输出