• bzoj2618 [Cqoi2006]凸多边形(半平面+S)


    Description

    逆时针给出n个凸多边形的顶点坐标,求它们交的面积。例如n=2时,两个凸多边形如下图:
    这里写图片描述
    则相交部分的面积为5.233。

    Input
    第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形。第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标。

    Output
    输出文件仅包含一个实数,表示相交部分的面积,保留三位小数。

    Sample Input
    2
    6
    -2 0
    -1 -2
    1 -2
    2 0
    1 2
    -1 2
    4
    0 -3
    1 -1
    2 2
    -1 0

    Sample Output
    5.233

    HINT
    100%的数据满足:2<=n<=10,3<=mi<=50,每维坐标为[-1000,1000]内的整数

    分析:
    半平面交
    一开始偷懒,在第一个多边形上切割
    结果就悲剧的WA了
    (虽然不知道为什么)

    我就设置了一个初始平面
    之后把每个多边形变成n条直线,在平面上切割,就Ale

    这里写图片描述

    tip

    这个OLE,多半是因为输出格式不对

    getline的操作很迷,老是记不住,现推又麻烦

    void getline(node x,node y)
    {
        a=y.y-x.y;
        b=x.x-y.x;
        c=x.y*y.x-x.x*y.y;
    }

    在切割的时候到底是<=还是>=还是对着样例调一调好了

    启示:

    不能偷懒

    练就扎实的基本功

    这里写代码片
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #define ll double
    
    using namespace std;
    
    const int N=1000;
    const ll eps=1e-10;
    struct node{
        ll x,y;
        node (ll xx=0,ll yy=0){
            x=xx;y=yy;
        } 
    };
    node po[N],p[N],q[N];
    ll a,b,c;
    int n,mm,m;
    
    int dcmp(ll x)
    {
        if (fabs(x)<eps) return 0;
        else if (x>0) return 1;
        else return -1;
    }
    
    node operator +(const node &a,const node &b){return node(a.x+b.x,a.y+b.y);}
    node operator -(const node &a,const node &b){return node(a.x-b.x,a.y-b.y);}
    node operator *(const node &a,const ll &b){return node(a.x*b,a.y*b);}
    node operator /(const node &a,const ll &b){return node(a.x/b,a.y/b);}
    
    ll Cross(node a,node b){return a.x*b.y-a.y*b.x;}
    ll Dot(node a,node b){return a.x*b.x+a.y*b.y;}
    
    void getline(node x,node y)
    {
        a=y.y-x.y;
        b=x.x-y.x;
        c=x.y*y.x-x.x*y.y;
    }
    
    node insert(node x,node y)
    {
        node ans;
        ll u=fabs(a*x.x+b*x.y+c);
        ll v=fabs(a*y.x+b*y.y+c);
        ans.x=(u*y.x+v*x.x)/(u+v);
        ans.y=(u*y.y+v*x.y)/(u+v);
        return ans;
    }
    
    void cut()
    {
        int cnt=0;
        for (int i=1;i<=mm;i++)  //mm
        {
            if (dcmp(a*p[i].x+b*p[i].y+c)<=0) q[++cnt]=p[i];
            else {
                if (dcmp(a*p[i-1].x+b*p[i-1].y+c)<0) q[++cnt]=insert(p[i-1],p[i]);
                if (dcmp(a*p[i+1].x+b*p[i+1].y+c)<0) q[++cnt]=insert(p[i],p[i+1]);
            }
        }
        for (int i=1;i<=cnt;i++) p[i]=q[i];
        p[0]=p[cnt]; p[cnt+1]=p[1];
        mm=cnt;
    }
    
    void doit()
    {
        po[0]=po[m]; po[m+1]=po[1];
        for (int i=1;i<=m;i++)   //<=m
        {
            getline(po[i],po[i+1]);
            cut();
        }
    }
    
    ll SS()
    {
        ll ans=0;
        for (int i=0;i<=mm;i++)
            ans+=Cross(p[i]-p[0],p[i+1]-p[0]);
        return fabs(ans)/2;
    }
    
    int main()
    {
        scanf("%d",&n);
        p[1].x=-1e10; p[1].y=-1e10;
        p[2].x=1e10; p[2].y=-1e10;
        p[3].x=1e10; p[3].y=1e10;
        p[4].x=-1e10; p[4].y=1e10;
        mm=4; p[mm+1]=p[1]; p[0]=p[mm];
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&m);
            for (int j=1;j<=m;j++)
                scanf("%lf%lf",&po[j].x,&po[j].y);
            doit();
        }
        printf("%0.3lf",SS());
        return 0;
    }
  • 相关阅读:
    systemctl命令
    linux下常用命令查看端口占用
    【PostgreSQL】存取jsonb
    tomcat内存溢出之PermGen space
    Spring事务传播机制
    java框架篇---spring aop两种配置方式
    Hibernate一对多实例
    Github 的系统内部都在用什么开源软件?
    这是一个关于软件开发的博客。
    JavaScript中数组的集合和映射
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673254.html
Copyright © 2020-2023  润新知