zoukankan      html  css  js  c++  java
  • hdu 4629 Burning (扫描线)

    Problem - 4629

      以前写过PSLG模拟的版本,今天写了一下扫描线做这题。

      其实这题可以用set存线段来做,类似于判断直线交的做法。不过实现起来有点麻烦,于是我就直接暴力求交点了。

    代码如下:

      1 #include <set>
      2 #include <queue>
      3 #include <cmath>
      4 #include <cstdio>
      5 #include <cstring>
      6 #include <iomanip>
      7 #include <iostream>
      8 #include <algorithm>
      9 
     10 using namespace std;
     11 
     12 const double EPS = 1e-10;
     13 inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
     14 typedef pair<double, double> Point;
     15 #define x first
     16 #define y second
     17 Point operator + (Point a, Point b) { return Point(a.x + b.x, a.y + b.y);}
     18 Point operator - (Point a, Point b) { return Point(a.x - b.x, a.y - b.y);}
     19 Point operator * (Point a, double p) { return Point(a.x * p, a.y * p);}
     20 Point operator / (Point a, double p) { return Point(a.x / p, a.y / p);}
     21 
     22 inline double cross(Point a, Point b) { return a.x * b.y - a.y * b.x;}
     23 inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y;}
     24 inline double veclen(Point a) { return sqrt(dot(a, a));}
     25 inline Point rotate(Point a) {
     26     double cosx = cos(0.001), sinx = sin(0.001);
     27     return Point(a.x * cosx - a.y * sinx, a.x * sinx + a.y * cosx);
     28 }
     29 
     30 struct Line {
     31     Point s, t;
     32     Line() {}
     33     Line(Point s, Point t) : s(s), t(t) {}
     34     Point vec() { return t - s;}
     35     Point point(double p) { return s + vec() * p;}
     36 } ;
     37 inline Point llint(Line a, Line b) { return a.point(cross(b.vec(), a.s - b.s) / cross(a.vec(), b.vec()));}
     38 void scan(Point &a) { cin >> a.x >> a.y;}
     39 const int N = 55;
     40 Point tri[N][4];
     41 
     42 bool check(int n) {
     43     for (int i = 0; i < n; i++) {
     44         for (int j = 0; j < 3; j++) {
     45             if (sgn(tri[i][j].x - tri[i][j + 1].x) == 0) return 1;
     46         }
     47     }
     48     return 0;
     49 }
     50 void adjust(int n) { for (int i = 0; i < n; i++) for (int j = 0; j < 4; j++) tri[i][j] = rotate(tri[i][j]);}
     51 inline bool between(Point p, Point a, Point b) { return sgn(dot(a - p, b - p)) <= 0;}
     52 bool cmpy(Point a, Point b) { return a.y < b.y;}
     53 
     54 bool triline(Line l, int id, Point *ip) {
     55     Point tmp[3];
     56     int tt = 0;
     57     for (int i = 0; i < 3; i++) {
     58         tmp[tt] = llint(l, Line(tri[id][i], tri[id][i + 1]));
     59         if (between(tmp[tt], tri[id][i], tri[id][i + 1])) tt++;
     60     }
     61     sort(tmp, tmp + tt, cmpy);
     62     ip[0] = tmp[0], ip[1] = tmp[tt - 1];
     63     return tt > 1;
     64 }
     65 
     66 typedef pair<double, int> Break;
     67 bool cmp(Break a, Break b) { return sgn(a.x - b.x) < 0 || sgn(a.x - b.x) == 0 && a.y < b.y;}
     68 Break ips_l[N << 2], ips_r[N << 2];
     69 double area[N], len_l[N], len_r[N], event[N * N << 4];
     70 void scanline(int n) {
     71     memset(area, 0, sizeof(area));
     72     int tt = 0;
     73     for (int i = 0; i < n; i++) {
     74         for (int j = 0; j < 3; j++) {
     75             Point a = tri[i][j], b = tri[i][j + 1];
     76             event[tt++] = a.x;
     77             for (int k = 0; k < n; k++) {
     78                 for (int l = 0; l < 3; l++) {
     79                     Point c = tri[k][l], d = tri[k][l + 1];
     80                     if (sgn(cross(b - a, d - c)) == 0) continue;
     81                     Point ip = llint(Line(a, b), Line(c, d));
     82                     //cout << ip.x << ' ' << ip.y << endl;
     83                     if (between(ip, a, b) && between(ip, c, d)) {
     84                         event[tt++] = ip.x;
     85                     }
     86                 }
     87             }
     88         }
     89     }
     90     sort(event, event + tt);
     91     tt = (int) (unique(event, event + tt) - event);
     92     Line cur;
     93     Point tmp[2];
     94     for (int i = 1, c, cnt; i < tt; i++) {
     95         if (sgn(event[i - 1] - event[i]) == 0) continue;
     96         c = 0;
     97         cur = Line(Point(event[i - 1] + EPS, 0.0), Point(event[i - 1] + EPS, 1.0));
     98         for (int j = 0; j < n; j++) {
     99             if (triline(cur, j, tmp)) {
    100                 ips_l[c++] = Break(tmp[0].y, 1), ips_l[c++] = Break(tmp[1].y, -1);
    101             }
    102         }
    103         sort(ips_l, ips_l + c, cmp);
    104         cnt = 0;
    105         memset(len_l, 0, sizeof(len_l));
    106         for (int j = 0; j < c; j++) {
    107             if (cnt > 0) len_l[cnt] += ips_l[j].x - ips_l[j - 1].x;
    108             cnt += ips_l[j].y;
    109         }
    110         c = 0;
    111         cur = Line(Point(event[i] - EPS, 0.0), Point(event[i] - EPS, 1.0));
    112         for (int j = 0; j < n; j++) {
    113             if (triline(cur, j, tmp)) {
    114                 ips_r[c++] = Break(tmp[0].y, 1), ips_r[c++] = Break(tmp[1].y, -1);
    115             }
    116         }
    117         sort(ips_r, ips_r + c, cmp);
    118         cnt = 0;
    119         memset(len_r, 0, sizeof(len_r));
    120         for (int j = 0; j < c; j++) {
    121             if (cnt > 0) len_r[cnt] += ips_r[j].x - ips_r[j - 1].x;
    122             cnt += ips_r[j].y;
    123         }
    124         for (int j = 1; j <= n; j++) area[j] += (len_l[j] + len_r[j]) * (event[i] - event[i - 1]) / 2;
    125     }
    126 }
    127 
    128 int main() {
    129     ios::sync_with_stdio(0);
    130     cout << setiosflags(ios::fixed) << setprecision(8);
    131     int T, n;
    132     cin >> T;
    133     while (T-- && cin >> n) {
    134         int tt = 0;
    135         for (int i = 0; i < n; i++) {
    136             for (int j = 0; j < 3; j++) scan(tri[tt][j]);
    137             tri[tt][3] = tri[tt][0];
    138             if (sgn(cross(tri[tt][1] - tri[tt][0], tri[tt][2] - tri[tt][0]))) tt++;
    139         }
    140         while (check(tt)) adjust(tt);
    141         scanline(tt);
    142         for (int i = 1; i <= n; i++) area[i] = fabs(area[i]);
    143         for (int i = 1; i <= n; i++) cout << area[i] << endl;
    144     }
    145     return 0;
    146 }
    View Code

    ——written by Lyon

  • 相关阅读:
    js正则 转载
    asp.net中打开新窗口的多种方法(转载)
    ajax有两种提交数据的方式,分别为get和post(转)
    DropDownList 绑定(转载)
    CentOS网络配置
    Java内存区域-- 运行时数据区域
    Spring Ioc--Bean装配
    Spring--Spring容器
    java正则表达式 --简单认识
    Leetcode 402:移除K个数字
  • 原文地址:https://www.cnblogs.com/LyonLys/p/hdu_4629_Lyon.html
Copyright © 2011-2022 走看看