湖南第十一届大学生程序设计大赛:多边形的公共部分(多边形面积并)

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\n",t++);
        else printf("Case %d: Yes\n",t++);
    }
    return 0;
}

 

posted @ 2016-08-10 17:12  樱花庄的龙之介大人  阅读(344)  评论(0编辑  收藏  举报