【hdu1632】半平面交模板

Polygons

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 174    Accepted Submission(s): 63


Problem Description
Given two convex polygons, they may or may not overlap. If they do overlap, they will do so to differing degrees and in different ways. Write a program that will read in the coordinates of the corners of two convex polygons and calculate the `exclusive or' of the two areas, that is the area that is bounded by exactly one of the polygons. The desired area is shaded in the following diagram:


 

Input
Input will consist of pairs of lines each containing the number of vertices of the polygon, followed by that many pairs of integers representing the x,y coordinates of the corners in a clockwise direction. All the coordinates will be positive integers less than 100. For each pair of polygons (pair of lines in the data file), your program should print out the desired area correct to two decimal places. The input will end with a line containing a zero (0).
 

Output
Output will consist of a single line containing the desired area written as a succession of eight (8) digit fields with two (2) digits after the decimal point. There will not be enough cases to need more than one line.
 

Sample Input
  
  
3 5 5 8 1 2 3 3 5 5 8 1 2 3 4 1 2 1 4 5 4 5 2 6 6 3 8 2 8 1 4 1 4 2 5 3 0
 

Sample Output
  
  
0.00 13.50
 

Source
uva

两个多边形的点都逆时针排序

用其中一个构造线去切割另一个

最后切割出来的多边形就是覆盖区域


/*
* @Author: Sky-J
* @Date:   2014-09-10 16:30:29
* @Last Modified by:   Sky-J
* @Last Modified time: 2014-09-10 19:40:46
*/

#define DeBUG
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <string>
#include <set>
#include <sstream>
#include <map>
#include <list>
#include <bitset>
using namespace std ;
#define zero {0}
#define INF 0x3f3f3f3f
#define EPS 1e-6
#define TRUE true
#define FALSE false
typedef long long LL;
const double PI = acos(-1.0);
//#pragma comment(linker, "/STACK:102400000,102400000")
inline int sgn(double x)
{
    return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);
}
#define N 100005
// Point class
struct Point;
typedef Point Vec;
struct Point
{
    double x, y;
    Point () {}
    Point(double a, double b)
    {
        x = a;
        y = b;
    }
};
Vec operator + (const Vec &a, const Vec &b) //点加法
{
    return Vec(a.x + b.x, a.y + b.y);
}
Vec operator - (const Vec &a, const Vec &b) //点减法
{
    return Vec(a.x - b.x, a.y - b.y);
}
Vec operator * (const Vec &a, const double &p) //点与常数相乘
{
    return Vec(a.x * p, a.y * p);
}
bool operator == (const Vec &a, const Point &b) //点相等判断
{
    return sgn(a.x - b.x) == 0 && sgn(a.y - b.y) == 0;
}
inline double dotDet(Vec a, Vec b)//点乘
{
    return a.x * b.x + a.y * b.y;
}
inline double crossDet(Vec a, Vec b)//叉乘
{
    return a.x * b.y - a.y * b.x;
}
inline double crossDet(Point o, Point a, Point b)//向量叉乘
{
    return crossDet(a - o, b - o);
}
inline bool onSeg(Point x, Point a, Point b)//判断点在线段ab上,加上||x==a||x==b在端点也算
{
    return sgn(crossDet(a - x, b - x)) == 0 && sgn(dotDet(a - x, b - x)) < 0 || x == a || x == b;
}
Point lineIntersect(Point P, Vec v, Point Q, Vec w)//直线相交返回交点
{
    Vec u = P - Q;
    double t = crossDet(w, u) / crossDet(v, w);//t必须为1/2的,可为什么要这么写呢?
    return P + v * t;
}
// Polygon class
struct Poly//平面类
{
    vector<Point> pt;//保存平面对应的端点
    Poly()
    {
        pt.clear();
    }
    ~Poly() {}
    Poly(vector<Point> pt0): pt(pt0) {} //使用vector进行初始化
    Point operator [](int x) const//重载[]返回对应端点
    {
        return pt[x];
    }
    int size()//返回对应平面点数
    {
        return pt.size();
    }
    double area()//得到面积,凹凸多边形均可
    {
        double ret = 0.0;
        int sz = pt.size();
        for (int i = 0; i < sz; i++)
        {
            int j = (i + 1) % sz;
            ret += crossDet(pt[i], pt[j]);
        }
        return ret / 2.0;
    }
    void output()
    {
        printf("%d\n", pt.size());
        for (int i = 0; i < pt.size(); i++)
        {
            printf("%lf %lf\n", pt[i].x, pt[i].y);
        }
    }
};
Poly cutPoly(Poly &poly, Point a, Point b)
{
    Poly ret = Poly();
    int n = poly.size();
    for (int i = 0; i < n; i++)
    {
        Point c = poly[i], d = poly[(i + 1) % n];
        if (sgn(crossDet(b - a, c - a)) >= 0)
            ret.pt.push_back(c);
        if (sgn(crossDet(b - a, c - d)) != 0)
        {
            Point ip = lineIntersect(a, b - a, c, d - c);
            if (onSeg(ip, c, d)) ret.pt.push_back(ip);
        }
    }
    return ret;
}

int main()
{
#ifdef DeBUGs
    freopen("C:\\Users\\Sky\\Desktop\\1.in", "r", stdin);
#endif
    int n1, n2;
    while (scanf("%d", &n1), n1)
    {
        Poly poly1, poly2;
        Point p;
        for (int i = 0; i < n1; i++)
        {
            scanf("%lf%lf", &p.x, &p.y);
            poly1.pt.push_back(p);
        }
        scanf("%d", &n2);
        for (int i = 0; i < n2; i++)
        {
            scanf("%lf%lf", &p.x, &p.y);
            poly2.pt.push_back(p);
        }
        double ret = poly1.area();
        if (sgn(ret) < 0)//通过计算多边形面积正负判断给出点的方向,逆时针为正
        {
            reverse(poly1.pt.begin(), poly1.pt.end());//点逆序
            ret = fabs(ret);
        }
        double area = poly2.area();
        if (sgn(area) < 0)
        {
            reverse(poly2.pt.begin(), poly2.pt.end());
            area = fabs(area);
        }
        poly2.pt.push_back(poly2.pt[0]);
        ret += area;
        Poly ans = poly1;
        for (int i = 0; i < n2; i++)
        {
            ans = cutPoly(ans, poly2[i], poly2[i + 1]);
        }
        // ans.output();
        printf("%8.2lf", ret - 2 * ans.area());
    }
    puts("");
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值