zoukankan      html  css  js  c++  java
  • 湖南第十一届大学生程序设计大赛:多边形的公共部分(多边形面积并)

    2025: 多边形的公共部分

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 6  Solved: 3
    [Submit][Status][Web Board]

    Description

    给定两个简单多边形, 你的任务是判断二者是否有面积非空的公共部分。如下图, (a)中的两个
    矩形只有一条公共线段,没有公共面积。
    (a) (b)
    在本题中,简单多边形是指不自交(也不会接触自身)、不含重复顶点并且相邻边不共线的多
    边形。
    注意: 本题并不复杂,但有很多看上去正确的算法实际上暗藏缺陷,请仔细考虑各种情况。  

    Input

    输入包含不超过 100 组数据。每组数据包含两行,每个多边形占一行。多边形的格式是:第一
    个整数 n 表示顶点的个数 (3<=n<=100), 接下来是 n 对整数(x,y) (-1000<=x,y<=1000), 即多边
    形的各个顶点, 按照逆时针顺序排列。  

    Output

    对于每组数据, 如果有非空的公共部分, 输出"Yes", 否则输出"No"。  

    Sample Input

    4 0 0 2 0 2 2 0 2
    4 2 0 4 0 4 2 2 2
    4 0 0 2 0 2 2 0 2
    4 1 0 3 0 3 2 1 2

    Sample Output

    Case 1: No
    Case 2: Yes


    去年感受了没模板的痛苦,有这个模板那这个题就是水题了...

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    const int maxn = 300;
    const double eps = 1e-8;
    const double pi = acos(-1.0);
    int dcmp(double x)
    {
        if(x > eps) return 1;
        return x < -eps ? -1 : 0;
    }
    struct Point
    {
        double x, y;
    };
    double cross(Point a,Point b,Point c) ///叉积
    {
        return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
    }
    Point intersection(Point a,Point b,Point c,Point d)
    {
        Point p = a;
        double t =((a.x-c.x)*(c.y-d.y)-(a.y-c.y)*(c.x-d.x))/((a.x-b.x)*(c.y-d.y)-(a.y-b.y)*(c.x-d.x));
        p.x +=(b.x-a.x)*t;
        p.y +=(b.y-a.y)*t;
        return p;
    }
    double PolygonArea(Point p[], int n)
    {
        if(n < 3) return 0.0;
        double s = p[0].y * (p[n - 1].x - p[1].x);
        p[n] = p[0];
        for(int i = 1; i < n; ++ i)
            s += p[i].y * (p[i - 1].x - p[i + 1].x);
        return fabs(s * 0.5);
    }
    double CPIA(Point a[], Point b[], int na, int nb)//ConvexPolygonIntersectArea
    {
        Point p[20], tmp[20];
        int tn, sflag, eflag;
        a[na] = a[0], b[nb] = b[0];
        memcpy(p,b,sizeof(Point)*(nb + 1));
        for(int i = 0; i < na && nb > 2; i++)
        {
            sflag = dcmp(cross(a[i + 1], p[0],a[i]));
            for(int j = tn = 0; j < nb; j++, sflag = eflag)
            {
                if(sflag>=0) tmp[tn++] = p[j];
                eflag = dcmp(cross(a[i + 1], p[j + 1],a[i]));
                if((sflag ^ eflag) == -2)
                    tmp[tn++] = intersection(a[i], a[i + 1], p[j], p[j + 1]); ///求交点
            }
            memcpy(p, tmp, sizeof(Point) * tn);
            nb = tn, p[nb] = p[0];
        }
        if(nb < 3) return 0.0;
        return PolygonArea(p, nb);
    }
    double SPIA(Point a[], Point b[], int na, int nb)///此函数中的 res 为两多边形相并面积
    {
        int i, j;
        Point t1[4], t2[4];
        double res = 0, num1, num2;
        a[na] = t1[0] = a[0], b[nb] = t2[0] = b[0];
        for(i = 2; i < na; i++)
        {
            t1[1] = a[i-1], t1[2] = a[i];
            num1 = dcmp(cross(t1[1], t1[2],t1[0]));
            if(num1 < 0) swap(t1[1], t1[2]);
            for(j = 2; j < nb; j++)
            {
                t2[1] = b[j - 1], t2[2] = b[j];
                num2 = dcmp(cross(t2[1], t2[2],t2[0]));
                if(num2 < 0) swap(t2[1], t2[2]);
                res += CPIA(t1, t2, 3, 3) * num1 * num2;
            }
        }
        return PolygonArea(a, na)+PolygonArea(b, nb) - res;
    }
    Point p1[maxn], p2[maxn];
    int n1, n2;
    int main()
    {
        int t = 1;
        while(scanf("%d", &n1) != EOF)
        {
            for(int i = 0; i < n1; i++) scanf("%lf%lf", &p1[i].x, &p1[i].y);
            scanf("%d",&n2);
            for(int i = 0; i < n2; i++) scanf("%lf%lf", &p2[i].x, &p2[i].y);
            double Area = SPIA(p1, p2, n1, n2);
            double Area1 = PolygonArea(p1,n1)+PolygonArea(p2,n2);
            if(Area==Area1) printf("Case %d: No
    ",t++);
            else printf("Case %d: Yes
    ",t++);
        }
        return 0;
    }
  • 相关阅读:
    判断应用程序是否是当前激活程序(获得焦点的程序)
    MFC的CListCtrl的使用与技巧
    VC/MFC中为程序定义全局快捷键
    [原]MFC中DIALOG(对话框)程序响应加速键(快捷键)
    问题:CListCtrl如何高亮选中一行 http://zhidao.baidu.com/question/100664911.html 扩展:单行、双行及完成状态的字体等等。。。
    C++读取INI文件
    键盘钩子监测按键后,获取键码及按键名称(MFC)
    一个分布式服务器集群架构方案
    Discuz!NT
    easyui validatebox 验证类型
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5757544.html
Copyright © 2011-2022 走看看