• POJ 1279 Art Gallery【半平面交】(求多边形的核)(模板题)


    <题目链接>

    题目大意:

    按顺时针顺序给出一个N边形,求N边形的核的面积。

    (多边形的核:它是平面简单多边形的核是该多边形内部的一个点集该点集中任意一点与多边形边界上一点的连线都处于这个多边形内部。)

    #include <cstdio>
    #include <cmath>
    #include <iostream>
    using namespace std;
    #define eps 1e-8
    const int MAXN=10017;
    int n;
    double r;
    int cCnt,curCnt;
    struct point
    {
        double x,y;
        point(double a=0,double b=0):x(a),y(b){}
    };
    point points[MAXN],p[MAXN],q[MAXN];
    
    
    point operator - (point A,point B) { return point(A.x-B.x,A.y-B.y); }
    
    double Cross(point A,point B){ return A.x*B.y-A.y*B.x; } 
    
    void getline(point x,point y,double &a,double &b,double   &c)      //得到直线的方程系数
    {                          
        a = y.y - x.y;
        b = x.x - y.x;
        c = y.x * x.y - x.x * y.y;
    }
    
    void initial()          //初始化放置多边形顶点的p数组
    {
        for(int i = 1; i <= n; i++)p[i] = points[i];
    
        p[n+1] = p[1];       
        p[0] = p[n];
    
        cCnt = n;
    }
    
    point intersect(point x,point y,double a,double b,double c)      //求点x、y形成的直线与已知直线a、b、c、的交点
    {
        double u = fabs(a * x.x + b * x.y + c);
        double v = fabs(a * y.x + b * y.y + c);
        point pt;
        pt.x=(x.x * v + y.x * u) / (u + v);
        pt.y=(x.y * v + y.y * u) / (u + v);
        return  pt;
    }
    
    void cut(double a,double b ,double c)
    {
        curCnt = 0;
        int i;
        for(i = 1; i <= cCnt; ++i)
        {                              
            if(a*p[i].x + b*p[i].y + c >= 0)q[++curCnt] = p[i];       // c因为精度问题,可能会偏小。所以有些点本应在右側而没在。
            
            else
            {
                if(a*p[i-1].x + b*p[i-1].y + c > 0) 
                {
                    
                    q[++curCnt] = intersect(p[i],p[i-1],a,b,c);
                }
                if(a*p[i+1].x + b*p[i+1].y + c > 0) //原理同上
                {
                    q[++curCnt] = intersect(p[i],p[i+1],a,b,c);
                }
            }
        }
        for(i = 1; i <= curCnt; ++i)p[i] = q[i];
        p[curCnt+1] = q[1];
        p[0] = p[curCnt];
        cCnt = curCnt;
    }
    
    void solve()
    {
        initial();
        for(int i = 1; i <= n; ++i)
        {
            double a,b,c;
            getline(points[i],points[i+1],a,b,c);
            cut(a,b,c);             //用原多边形的边界去切割p数组表示的内核多边形
        }
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            for(int i = 1; i <= n; i++)    
            {
                scanf("%lf%lf",&points[i].x,&points[i].y);
            }
            points[n+1] = points[1];
            solve();    
            if(cCnt<=2)         //如果1或者两个点,直接输出面积为0.00
                printf("%.2lf
    ",0);
            else
            {
                double area=0;       //利用叉乘算出多边形的面积
                for(int i=1;i<cCnt;i++)
                {
                     area+=Cross(p[i]-p[1],p[i+1]-p[1]);
                }
                printf("%.2lf
    ",fabs(area)/2.0);
            }
        }
        return 0;
    }

    2018-08-03

  • 相关阅读:
    Android开发系列(十七)QQ聊天之Android显示Gif ——在TextView中添加动态表情
    玩转Hook——Android权限管理功能探讨(二)
    玩转Hook——Android权限管理功能探讨(一)
    由一个简单算法想到的程序员素养问题
    Android手机间无线互传功能探索及实现
    从字节码的角度看Java内部类与外部类的互相访问
    HttpClient与HttpUrlConnection下载速度比较
    记一道有趣的Twitter面试题
    Android改进版CoverFlow效果控件
    Android应用如何监听自己是否被卸载及卸载反馈功能的实现(第二版)
  • 原文地址:https://www.cnblogs.com/00isok/p/9416828.html
Copyright © 2020-2023  润新知