我的半平面交模板

昨天研究了一下午的半平面交算法,发现要看懂网上的模板真的是不容易啊。。。。orz,然后就从最基本的开始了,先去打印了一份zzy的n(logn)求半平面交的论文

研究了一发,大概思路懂了,然后看到网上有一份别人推荐的模板,就接着研究模板去了,后来看着模板,自己再涂涂改改,就整理出了我的第一份半平面交模板,可喜可贺~~~得意,下面就是我的模板还有注释一些我的理解

其实就是poj 的2451

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const double eps=1e-8;
int dq[200005],top,bot,pn;
double marea;
struct P
{
    double x,y;
    P (){}
    P (double x,double y):x(x),y(y){
    }
    P operator -(P p){
        return P(x-p.x,y-p.y);
    }
    P operator +(P p){
        return P(x+p.x,y+p.y);
    }
    P operator *(double d){
        return P(x*d,y*d);
    }
    double det(P p){
        return x*p.y-y*p.x;
    }
}p[200005];
struct Line
{
    P a,b;
    double angle;
}l[1000000];
//判断大小函数。
int dblcmp(double k)
{
    if(fabs(k)<eps)
    return 0;
    return k>0?1:-1;
}
//极角排序,相同的则按靠里面的放前
bool cmp(Line a,Line b)
{
    int d=dblcmp(a.angle-b.angle);
    if(!d)
    return dblcmp((b.a-a.a).det(b.b-a.a))>0;
    return d<0;
}
//求直线a,b的交点函数
P in(Line a,Line b)
{
    return a.a+(a.b-a.a)*((b.b-b.a).det(b.a-a.a) / (b.b-b.a).det(a.b-a.a));
}
//b,c为半平面的顶点的两条直线,若它们的交点在新加入的半平面外,则返回1;
bool judge(Line a,Line b,Line c)
{
    P r=in(b,c);
    return dblcmp((a.a-r).det(a.b-r))<0;
}
int n;
void HalfPlaneIntersect()
{
    int i,j;
    //按极角排序
    sort(l,l+n,cmp);
    for(i=0,j=0;i<n;i++)
    {
        if(dblcmp(l[i].angle-l[j].angle)>0)  //存在极角相同的则取第一个
        l[++j]=l[i];
    }
    n=j+1;
    //dq为双端队列,存线段的编号信息
    dq[0]=0;
    dq[1]=1;
    top=1;
    bot=0;
    for(i=2;i<n;i++)
    {
        //若顶端的两条直线的交点在新半平面l[i]外,那么这个顶点就弹出
        while(top>bot && judge(l[i],l[dq[top]],l[dq[top-1]])) top--;
        //旋转一圈左右,如果底部的交点在新加入的半平面外,底部弹出
        while(top>bot && judge(l[i],l[dq[bot]],l[dq[bot+1]])) bot++;
        dq[++top]=i;
    }
    //若顶部的交点不在底部的半平面内,则顶部弹出
    while(top>bot && judge(l[dq[bot]],l[dq[top]],l[dq[top-1]])) top--;
    //同理若底部的交点不在顶部的半平面内,则底部弹出
    while(top>bot && judge(l[dq[top]],l[dq[bot]],l[dq[bot+1]])) bot++;
    //底部加入进来,方便计算半平面交成的凸多边形顶点
    dq[++top]=dq[bot];
    for(pn=0,i=bot;i<top;i++,pn++)
    {
        p[pn]=in(l[dq[i+1]],l[dq[i]]);
    }
}
void getarea()
{
    marea=0;
    if(pn<3)
    marea=0;
    //面积计算公式,也可以用叉乘直接算
    for(int i=0;i<pn;i++)
    {
        marea+=(p[i].x*p[i+1].y-p[i].y*p[i+1].x);
    }
    marea+=(p[pn-1].x*p[0].y-p[pn-1].y*p[0].x);
    marea=fabs(marea);
    marea/=2.0;
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%lf%lf%lf%lf",&l[i].a.x,&l[i].a.y,&l[i].b.x,&l[i].b.y);
        l[i].angle=atan2(l[i].b.y-l[i].a.y,l[i].b.x-l[i].a.x);
    }
    //添加题意中的边界
    l[n].a.x=0;l[n].a.y=0;l[n].b.x=10000;l[n].b.y=0;
    l[n].angle=atan2(l[n].b.y-l[n].a.y,l[n].b.x-l[n].a.x);
    n++;
    l[n].a.x=10000;l[n].a.y=0;l[n].b.x=10000;l[n].b.y=10000;
    l[n].angle=atan2(l[n].b.y-l[n].a.y,l[n].b.x-l[n].a.x);
    n++;
    l[n].a.x=10000;l[n].a.y=10000;l[n].b.x=0;l[n].b.y=10000;
    l[n].angle=atan2(l[n].b.y-l[n].a.y,l[n].b.x-l[n].a.x);
    n++;
    l[n].a.x=0;l[n].a.y=10000;l[n].b.x=0;l[n].b.y=0;
    l[n].angle=atan2(l[n].b.y-l[n].a.y,l[n].b.x-l[n].a.x);
    n++;
    //半平面交
    HalfPlaneIntersect();
    //求面积
    getarea();
    printf("%.1lf\n",marea);
    return 0;
}


1. DFS(深度优先搜索) DFS是一种常用的搜索算法,它可以用来搜索图、树等结构。具体实现时,我们可以使用递归或栈来实现。 2. BFS(广度优先搜索) BFS是一种常用的搜索算法,它可以用来搜索图、树等结构。具体实现时,我们可以使用队列来实现。 3. 动态规划(Dynamic Programming) 动态规划是一种常用的算法思想,它通常用来解决最优化问题。具体实现时,我们需要定义状态转移方程和边界条件。 4. 贪心算法(Greedy Algorithm) 贪心算法是一种常用的算法思想,它通常用来解决最优化问题。具体实现时,我们需要找到一种贪心策略,并证明该策略的正确性。 5. 分治算法(Divide and Conquer) 分治算法是一种常用的算法思想,它通常用来解决复杂的问题。具体实现时,我们需要将问题分成若干个子问题,然后递归地解决这些子问题。 6. 排序算法(Sorting Algorithm) 排序算法是一种常用的算法,它可以对数据进行排序。常见的排序算法包括冒泡排序、选择排序、插入排序、归并排序、快速排序等。 7. 字符串匹配算法(String Matching Algorithm) 字符串匹配算法是一种常用的算法,它可以在文本串中查找一个模式串。常见的字符串匹配算法包括暴力匹配算法、KMP算法、Boyer-Moore算法等。 8. 图论算法(Graph Theory Algorithm) 图论算法是一种常用的算法,它可以用来解决图论问题。常见的图论算法包括最短路径算法、最小生成树算法、拓扑排序算法、最大流算法等。 9. 数学算法(Mathematical Algorithm) 数学算法是一种常用的算法,它可以用来解决各种数学问题。常见的数学算法包括欧几里得算法、素数筛法、快速幂算法、高斯消元法等。 10. 计算几何算法(Computational Geometry Algorithm) 计算几何算法是一种常用的算法,它可以用来解决各种几何问题。常见的计算几何算法包括凸包算法、平面算法、点线面的位置关系判断等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值