JDFZOJ 1005 多边形面积 扫描线

题目大意:给出N个凸多边形,求这些多边形的面积并。

思路:N只有不到10,乱搞就可以。还有一种更优的解法,似乎只需要O(n^2logn)的时间就可以解决。但是我并不会,想了解的参照:http://wyfcyx.is-programmer.com/posts/80378.html

下面说乱搞的思路。由于都是凸多边形,那么任意一条垂直于x轴的直线在多边形内的区域一定是一条线段(或者什么都没有),那么我们将所有多边形按照梯形进行剖分,求出每个部分的梯形中腰长度并就可以算出总的面积了。

题目网址见:http://oj.jdfz.com.cn:8081/oldoj/problem.php?id=1005

CODE:

#define _CRT_SECURE_NO_WARNINGS

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define MAX 20
#define EPS 1e-8
using namespace std;
#define max(a,b) ((a) > (b) ? (a):(b))
#define min(a,b) ((a) < (b) ? (a):(b))
#define INRANGE(x,y,c) ((c <= y && c >= x) || (c <= x && c >= y))

struct Point{
    double x,y;

    Point(double _,double __):x(_),y(__) {}
    Point() {}
    Point operator +(const Point &a)const {
        return Point(x + a.x,y + a.y);
    }
    Point operator -(const Point &a)const {
        return Point(x - a.x,y - a.y);
    }
    Point operator *(double a)const {
        return Point(x * a,y * a);
    }
    void Read() {
        scanf("%lf%lf",&x,&y);
    }
}temp[1010];

inline double Calc(const Point &p1,const Point &p2)
{
    return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}

inline double Cross(const Point &p1,const Point &p2)
{
    return p1.x * p2.y - p1.y * p2.x;
}

struct Segment{
    Point p1,p2,v;

    Segment(Point _,Point __,Point ___):p1(_),p2(__),v(___) {}
    Segment() {}
    bool OnSegment(const Point &p) {
        if(p1.x == p2.x)    return INRANGE(p1.y,p2.y,p.y);
        return INRANGE(p1.x,p2.x,p.x);
    }
}*src[MAX][1010],save[MAX * 1010];
int cnt_seg;

struct Interval{
    double x,y;

    Interval(double _,double __):x(_),y(__) {}
    Interval() {}
    bool operator <(const Interval &a)const {
        if(x == a.x)    return y < a.y;
        return x < a.x;
    }
}interval[MAX * 1010];

inline Point GetIntersection(const Segment &l1,const Segment &l2)
{
    Point u = l1.p1 - l2.p1;
    double t = Cross(l2.v,u) / Cross(l1.v,l2.v);
    return l1.p1 + l1.v * t;
}

inline Segment *MakeSegment(const Point &p1,const Point &p2)
{
    save[++cnt_seg] = Segment(p1,p2,p2 - p1);
    return &save[cnt_seg];
}

inline Interval GetInterval(Segment *src[],double x)
{
    Interval re(0,0);
    for(int i = 1; src[i] != NULL; ++i) {
        Point intersection = GetIntersection(*src[i],Segment(Point(x,0),Point(x,0),Point(0,1)));
        if(src[i]->OnSegment(intersection)) {
            if(!re.x)   re.x = intersection.y;
            else        re.y = intersection.y;
        }
    }
    if(re.x > re.y)  swap(re.x,re.y);
    return re;
}

int cnt;
double divide[1010 * 1010];

int main()
{
    cin >> cnt;
    for(int points,i = 1; i <= cnt; ++i) {
        scanf("%d",&points);
        for(int j = 1; j <= points; ++j)
            temp[j].Read();
        for(int j = 1; j < points; ++j)
            src[i][j] = MakeSegment(temp[j],temp[j + 1]);
        src[i][points] = MakeSegment(temp[points],temp[1]);
    }
    int divides = 0;
    for(int i = 1; i <= cnt_seg; ++i)
        for(int j = i + 1; j <= cnt_seg; ++j) {
            if(fabs(Cross(save[i].v,save[j].v)) < EPS)   continue;
            Point intersection = GetIntersection(save[i],save[j]);
            divide[++divides] = intersection.x;
        }
    sort(divide + 1,divide + divides + 1);
    double area = .0;
    for(int i = 1; i < divides; ++i) {
        double x = (divide[i + 1] + divide[i]) / 2;
        int intervals = 0;
        for(int j = 1; j <= cnt; ++j)
            interval[++intervals] = GetInterval(src[j],x);
        sort(interval + 1,interval + intervals + 1);

        double now = .0,l = interval[1].x,r = interval[1].y;
        for(int j = 2; j <= intervals; ++j)
            if(interval[j].x <= r)
                r = max(r,interval[j].y);
            else {
                now += r - l;
                l = interval[j].x;
                r = interval[j].y;
            }
        now += r - l;
        area += now * (divide[i + 1] - divide[i]);
    }
    cout << fixed << setprecision(3) << area << endl;
    return 0;
}

时间: 2024-08-03 03:06:10

JDFZOJ 1005 多边形面积 扫描线的相关文章

ZOJ 1010 Area 求任意多边形面积

主要判断是否是多边形:1.n<3 : 2.非相邻两条线段不相交 #include <iostream> #include <cmath> #include <stdio.h> using namespace std; #define eps 1e-8 int sig(double x) { if(x<-eps) return -1; if(x>eps) return 1; return 0; } struct point { double x,y; }

多边形面积公式

多边形面积公式 设点顺序 (x1 y1) (x2 y2)    ... (xn yn) 则面积等于 |x1   y1 |      |x2   y2|                  |xn   yn| 0.5 * abs( |            | +   |           | + ...... +   |           | ) |x2   y2 |      |x3   y3|                  |x1   y1| 其中        |x1   y1| |

三角剖分求多边形面积的交 HDU3060

1 //三角剖分求多边形面积的交 HDU3060 2 3 #include <iostream> 4 #include <cstdio> 5 #include <cstring> 6 #include <stack> 7 #include <queue> 8 #include <cmath> 9 #include <algorithm> 10 using namespace std; 11 12 const int max

poj 1654 Area(求多边形面积)

题意:从原点出发向八个方向走,所给数字串每个数字代表一个方向,终点与原点连线,求所得多边形面积: 思路:(性质)共起点的两向量叉积的一半为两向量围成三角形的面积.以此计算每条边首尾两个向量的叉积,求和,除二: #include<cstdio> #include<iostream> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const dou

poj1408——叉积求多边形面积

poj1408——叉积求多边形面积 Fishnet Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 1853   Accepted: 1185 Description A fisherman named Etadokah awoke in a very small island. He could see calm, beautiful and blue sea around the island. The previou

地球椭球面上多边形面积量算(C++代码)

昨天突然测试的时候发现以前产品中写的地球椭球面上面积计算的代码有点问题,于是今天就彻底修正,从QGIS中抠出代码来用C++重写了一下,新代码可以比较准确计算椭球面上多边形的面积,这个基础函数对空间量算功能中的面积量测非常重要,在这里共享出来供大家参考甚至直接拿过去用. 头文件如下: /** * @file DistanceArea.h * @brief 椭球面上计算多边形面积的接口文件 * @details * @author zxg * @date 2015年5月15日 * @version

多边形面积模板

HDU 2036 改革春风吹满地 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 20033    Accepted Submission(s): 10256 Problem Description “ 改革春风吹满地, 不会AC没关系; 实在不行回老家, 还有一亩三分地. 谢谢!(乐队奏乐)”话说部分学生心态极好,每天就知道游戏,这次

HDU 3060 多边形面积并

Area2 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1197    Accepted Submission(s): 278 Problem Description 小白近期又被空军特招为飞行员,參与一项实战演习.演习的内容还是轰炸某个岛屿(这次的岛屿非常大,非常大非常大非常大,大到炸弹怎么扔都能全然在岛屿上引爆),看来小白确实是

hdu 1255 覆盖的面积(扫描线)

http://acm.hdu.edu.cn/showproblem.php?pid=1255 一道挺简单的题,让我折腾了许久.主要卡在了更新节点后维护父亲节点上.后来思路明确了就很容易了. 节点信息: l,r:区间端点 cnt:区间被覆盖的次数,cnt = 0说明没有被完全覆盖. len1:区间被覆盖的长度 len2:区间至少被两条线段覆盖的长度. 只要找到父亲节点与子节点在len1,len2,cnt的关系就简单了. #include <stdio.h> #include <iostre