码迷,mamicode.com
首页 > 其他好文 > 详细

sgu209:Areas(计算几何)

时间:2015-03-14 13:55:04      阅读:201      评论:0      收藏:0      [点我收藏+]

标签:

题意:
给出一些直线。这些直线将平面分成好多块。求这些块中各个封闭图形的面积。

分析:
①我们需要求出两两直线的交点;
②再对每条直线上的交点排序,藉此来离散出所有的线段(正反两条边);
③对于连向一个点的几条线段,对它们进行极角排序,相邻的两条线段我们给它们之间连一条边,我们脑补一下应该可以知道怎样可以保证逆时针连边;
④找循环,利用叉积求面积。

ps. vector的调试真心不爽…

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#define pb push_back
#include <utility>
#define fi first
#define se second
#define mp make_pair
#include <stack>
using namespace std;
const int MAXN = 100;
const int MAXE = MAXN*MAXN<<1;
const double eps = 1e-8;
typedef double DB;

int n;
#define sqr(x) ((x)*(x))
struct pot
{
    double x, y;    
    pot(double x = 0, double y = 0):x(x), y(y){}
    inline double len() {return sqrt(sqr(x)+sqr(y));}
    inline void read() {scanf("%lf%lf", &x, &y);}
    inline pot unit() 
    {
        double d = len();
        return pot(x/d, y/d);
    }
    inline double ang() {return atan2(y, x);}
};
typedef pot vec;
struct Line
{
    pot p;
    vec v;
    Line(){}
    Line(pot p, vec v):p(p), v(v){}
}lines[MAXN];
vector<pot> points;

struct Edge
{
    int sz;
    int head[MAXE], to[MAXE], ne[MAXE];
    Edge()
    {
        sz = 0;
        memset(head, -1, sizeof(head)); 
    }
    inline void add(int u, int v)
    {
        to[sz] = v;ne[sz] = head[u];
        head[u] = sz++; 
    }
}E;

int next[MAXE];

bool vis[MAXE];

vector<DB> ans;

inline int dcmp(double x)
{
    if(fabs(x) <= eps) return 0;
    else return x>0?1:-1;   
}

inline pot operator + (const vec &a, const vec &b) {return vec(a.x+b.x, a.y+b.y);}
inline pot operator - (const vec &a, const vec &b) {return vec(a.x-b.x, a.y-b.y);}
inline double operator * (const vec &a, const vec &b) {return a.x*b.x+a.y*b.y;}
inline double operator ^ (const vec &a, const vec &b) {return a.x*b.y-a.y*b.x;}
inline pot operator * (const vec &a, double k) {return vec(a.x*k, a.y*k);}
inline pot operator / (const vec &a, double k) {return vec(a.x/k, a.y/k);}
inline bool operator < (const vec &a, const vec &b) {return dcmp(a.x-b.x) < 0 || (dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) < 0);}
inline bool operator == (const vec &a, const vec &b) {return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;}

inline pot get_line_intersection(const pot &p, const vec &v, const pot &q, const vec &w)
{
    vec u = p-q;
    double t = (w^u)/(v^w);
    return p+v*t;
}

inline bool parallel(const Line &a, const Line &b) {return dcmp(a.v^b.v) == 0;}

inline int get_pot_id(const pot &p) {return lower_bound(points.begin(), points.end(), p)-points.begin();}

inline bool cmp(DB a, DB b) {return dcmp(a-b) == 0;}

inline void init()
{
    scanf("%d", &n);
    for(int i = 0; i < n; ++i)
    {
        pot a, b;
        a.read();b.read();
        lines[i] = Line(a, b-a);    
    }
    for(int i = 0; i < n; ++i)
        for(int j = i+1; j < n; ++j)
            if(!parallel(lines[i], lines[j]))
                points.pb(get_line_intersection(lines[i].p, lines[i].v, lines[j].p, lines[j].v));
    sort(points.begin(), points.end());
    points.erase(unique(points.begin(), points.end()), points.end());
    for(int i = 0; i < n; ++i)
    {
        vector<DB> nodes;
        vec d = lines[i].v.unit();  
        for(int j = 0; j < n; ++j)
            if(!parallel(lines[i], lines[j]))
            {
                pot inter = get_line_intersection(lines[i].p, lines[i].v, lines[j].p, lines[j].v);
                nodes.pb((inter-lines[i].p)*d);
            }
        sort(nodes.begin(), nodes.end());
        nodes.erase(unique(nodes.begin(), nodes.end(), cmp), nodes.end());
        for(int j = 1, sz = nodes.size(); j < sz; ++j)
        {
            int a = get_pot_id(lines[i].p+d*nodes[j]);
            int b = get_pot_id(lines[i].p+d*nodes[j-1]);
            E.add(a, b);E.add(b, a);
        }
    }
    memset(next, -1, sizeof(next));
    for(int i = 0, sz = points.size(); i < sz; ++i)
    {
        vector<pair<DB, int> > PA;
        for(int j = E.head[i]; j != -1; j = E.ne[j])
            PA.pb(mp((points[E.to[j]]-points[i]).ang(), j));
        sort(PA.begin(), PA.end());
        for(int j = 0, sz = PA.size(); j < sz; ++j)
            next[PA[(j+1)%sz].se^1] = PA[j].se; 
    }
}

inline void work()
{
    for(int i = 0; i < E.sz; ++i)
        if(!vis[i])
        {
            stack<int> s;
            int j = i;
            do
            {
                if(!s.empty() && (s.top()^1) == j)
                    s.pop();
                else s.push(j);
                vis[j] = true;
                j = next[j];
                if(j == -1) break;
            }while(!vis[j]);
            if(i == j)
            {
                DB area = 0;
                while(!s.empty())
                {
                    area += (points[E.to[s.top()^1]]^points[E.to[s.top()]]);
                    s.pop();
                }
                area *= 0.5; 
                if(dcmp(area) > 0)
                    ans.pb(area);   
            }
        }
}

inline void print()
{
    printf("%d\n", ans.size());
    sort(ans.begin(), ans.end());
    for(int i = 0, sz = ans.size(); i < sz; ++i)
        printf("%.4lf\n", ans[i]);
}

int main()
{
    init();
    work();
    print();
    return 0;   
}

sgu209:Areas(计算几何)

标签:

原文地址:http://blog.csdn.net/qq_20118433/article/details/44258569

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!