SGU 209. Areas

209. Areas

time limit per test: 0.25 sec.
memory limit per test: 65536 KB
input: standard
output: standard




Consider N different lines on the plane. They divide it to several parts,some of which are finite, some infinite. 

Your task in this problem is for each finite part to find its area. 

Input

The first line of the input file contains N — the number of lines (1 ≤ N ≤ 80). Each of next N lines contains four integer numbers x1, y1, x2 and y2 — the coordinates of two different points of the line. 

All coordinates do not exceed 102 by their absolute value. 

No two lines coincide. 

Output

First output K — the number of finite parts among those the lines divide the plane to. 

Next K lines of the output file must contain area parts sorted in non-decreasing order. You answer must be accurate up to 10-4

Due to floating point precision losses possible, do not consider parts with area not exceeding 10-8

Sample test(s)

Input
 
 

0 0 1 0 
1 0 1 1 
1 1 0 1 
0 1 0 0 
0 0 1 1 
 
 

Output
 
 

0.5000 
0.5000 
 
 

 


题意

求平面上一堆直线围成的所有封闭多边形面积。


 

ID: Date'n'Time: Name: Task: .Ext: Status: Time: Memory:
1587815 27.08.14 15:40 HuZhifeng 209 .CPP Accepted 15 ms 458 kb
1587814 27.08.14 15:00 HuZhifeng 209 .CPP Wrong answer on test 12 15 ms 554 kb
1587813 27.08.14 14:55 HuZhifeng 209 .CPP Memory Limit Exceeded on test 12 218 ms 99406 kb
1587812 27.08.14 14:53 HuZhifeng 209 .CPP Runtime Error on test 12 15 ms 378 kb
 
又RE又ME又WA。。太爽啦!
 
坑爹题啊!
copy叉姐的。。。不忍直视。
 
#include <bits/stdc++.h>
#define rep(_i, _j) for(int _i = 1; _i <= _j; ++_i)
const int inf = 0x3f3f3f3f;
typedef long long LL;
typedef double DB;
using namespace std;
/*{ 基本定义,二维点,向量,叉积,点积,基本运算。*/

const DB eps = 1e-8;
#define sqr(x) ((x) * (x))
int dcmp(DB x) {
    return x < -eps ? -1 : eps < x;
}
bool chk_equality(DB x, DB y) {
    return dcmp(x - y) == 0;
}

struct Point {
    DB x, y;
    Point() {}
    Point(DB x, DB y): x(x), y(y) {}
    DB arg() {
        return atan2(y, x);
    }
    DB norm() {
        return sqrt(sqr(x) + sqr(y));
    }
    Point normalize() {
        DB d = norm();
        return Point(x / d, y / d);
    }
    void read() {
        scanf("%lf%lf", &x, &y);
    }
};
typedef Point Vector;
bool operator == (const Point a, const Point b) {
    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
bool operator < (const Point a, const Point b) {
    return dcmp(a.x - b.x) < 0 || (dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) < 0);
}
Vector operator + (Point a, Point b) {
    return Vector(a.x + b.x, a.y + b.y);
}
Vector operator - (Point a, Point b) {
    return Vector(a.x - b.x, a.y - b.y);
}
Vector operator * (Vector v, DB p) {
    return Vector(v.x * p, v.y * p);
}
Vector operator / (Vector v, DB p) {
    return Vector(v.x / p, v.y / p);
}
DB dot(Vector a, Vector b) {
    return a.x * b.x + a.y * b.y;
}
DB cross(Vector a, Vector b) {
    return a.x * b.y - a.y * b.x;
}
DB length(Vector a) {
    return sqrt(dot(a, a));
}

/*} end*/

struct Line {
    Point p;
    Vector d;
    Line() {}
    Line(Point p, Vector d): p(p), d(d) {}
};
bool operator == (Line a, Line b) {
    return a.p == b.p && dcmp(cross(a.d, b.d)) == 0;
}
/*{ 常用函数*/

Point get_intersection(Line a, Line b) {
    DB s1 = cross(a.p - b.p, b.d);
    DB s2 = cross(a.p + a.d - b.p, b.d);
    return (a.p * s2 - (a.p + a.d) * s1) / (s2 - s1);
}

/*} end*/

const int maxn = 80 + 2;

int n;
Line lines[maxn];
Point tmp1, tmp2;
vector<Point> points;
int get_point_id(Point a) {
    return lower_bound(points.begin(), points.end(), a) - points.begin();
}
const int maxv = maxn;
const int maxe = maxv * maxv * 2;
struct Edge {
    int edge;
    int head[maxe], to[maxe], next[maxe];
    Edge() {
        edge = 0;
        memset(head, -1, sizeof head);
    }
    void addedge(int u, int v) {
        to[edge] = v;
        next[edge] = head[u];
        head[u] = edge++;
    }
} E;
int next[maxe];
bool vis[maxe];

int main() {
#ifndef ONLINE_JUDGE
    freopen("209.in", "r", stdin); freopen("209.out", "w", stdout);
#endif
    cin >> n;
    for(int i = 0; i < n; ++i) {
        tmp1.read(), tmp2.read();
        lines[i] = Line(tmp1, tmp2 - tmp1);
    }
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < i; ++j) {
            if(!chk_equality(cross(lines[i].d, lines[j].d), 0)) {
                points.push_back(Point(get_intersection(lines[i], lines[j])));
            }
        }
    }
    sort(points.begin(), points.end());
    points.erase(unique(points.begin(), points.end()), points.end());
    for(int i = 0; i < n; ++i) {
        vector<DB> lambdas;
        Vector d = lines[i].d.normalize();
        for(int j = 0; j < n; ++j) {
            if(!chk_equality(cross(d, lines[j].d), 0)) {
                lambdas.push_back(dot(get_intersection(lines[i], lines[j]) - lines[i].p, d));
            }
        }
        sort(lambdas.begin(), lambdas.end());
        lambdas.erase(unique(lambdas.begin(), lambdas.end(), chk_equality), lambdas.end());
        for(int j = 1, sz = lambdas.size(); j < sz; ++j) {
            int a = get_point_id(lines[i].p + d * lambdas[j]);
            int b = get_point_id(lines[i].p + d * lambdas[j - 1]);
            E.addedge(b, a);
            E.addedge(a, b);
        }
    }
    memset(next, -1, sizeof next);
    for(int i = 0, sz = points.size(); i < sz; ++i) {
        vector<pair<DB, int> > adjacent;
        for(int j = E.head[i]; j != -1; j = E.next[j]) {
            adjacent.push_back(make_pair((points[E.to[j]] - points[i]).arg(), j));
        }
        sort(adjacent.begin(), adjacent.end());
        for(int j = 0, sz = adjacent.size(); j < sz; ++j) {
            next[adjacent[(j + 1) % sz].second ^ 1] = adjacent[j].second;
        }
    }
    memset(vis, false, sizeof vis);
    vector<DB> areas;
    for(int i = 0; i < E.edge; ++i) {
        if(!vis[i]) {
            vector<int> boundary;
            int j = i;
            do {
                if(!boundary.empty() && (boundary.back() ^ j) == 1) {
                    boundary.pop_back();
                } else {
                    boundary.push_back(j);
                }
                vis[j] = true;
                j = next[j];
            } while(!vis[j]);
            if(i == j) {
                DB area = 0.0;
                for(int k = 0, sz = boundary.size(); k < sz; ++k) {
                    area += cross(points[E.to[boundary[k] ^ 1]], points[E.to[boundary[k]]]);
                }
                area /= 2.0;
                if(dcmp(area) > 0) {
                    areas.push_back(area);
                }
            }
        }
    }
    sort(areas.begin(), areas.end());
    printf("%d\n", (int)areas.size());
    for(int i = 0, sz = areas.size(); i < sz; ++i) {
        printf("%.4lf\n", areas[i]);
    }
    return 0;
}
View Code

 

posted @ 2014-08-27 19:45  sbit  阅读(323)  评论(0编辑  收藏  举报