• poj 3743 LL’s cake (PSLG,Accepted)


    3743 -- LL’s cake

      搞了好久都过不了,看了下题解是用PSLG来做的。POJ 2164 && LA 3218 Find the Border (Geometry, PSLG 平面直线图) - LyonLys - 博客园 这篇里面写过一下,就是把点都提取出来,然后模拟沿着边界移动,找到多边形并计算面积。

      而我的做法是直接模拟多边形切割,各种超时爆内存。先留着,看以后能不能用这个来过。

    没过的代码:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <cmath>
      6 #include <vector>
      7 #include <queue>
      8 
      9 using namespace std;
     10 
     11 const double EPS = 1e-4;
     12 inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
     13 struct Point {
     14     double x, y;
     15     Point() {}
     16     Point(double x, double y) : x(x), y(y) {}
     17     Point operator + (Point a) { return Point(x + a.x, y + a.y);}
     18     Point operator - (Point a) { return Point(x - a.x, y - a.y);}
     19     Point operator * (double p) { return Point(x * p, y * p);}
     20     Point operator / (double p) { return Point(x / p, y / p);}
     21     bool operator < (Point a) const { return sgn(x - a.x) < 0 || sgn(x - a.x) == 0 && y < a.y;}
     22     bool operator == (Point a) const { return sgn(x - a.x) == 0 && sgn(y - a.y) == 0;}
     23 } ;
     24 
     25 inline double cross(Point a, Point b) { return a.x * b.y - a.y * b.x;}
     26 inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y;}
     27 inline double veclen(Point x) { return sqrt(dot(x, x));}
     28 inline Point normal(Point x) { return Point(-x.y, x.x) / veclen(x);}
     29 inline Point vecunit(Point x) { return x / veclen(x);}
     30 
     31 struct Line {
     32     Point s, t;
     33     Line() {}
     34     Line(Point s, Point t) : s(s), t(t) {}
     35     Point vec() { return t - s;}
     36     Point point(double x) { return s + vec() * x;}
     37 } ;
     38 inline Point llint(Line a, Line b) { return a.point(cross(b.vec(), a.s - b.s) / cross(a.vec(), b.vec()));}
     39 inline bool onseg(Point x, Point s, Point t) { return sgn(cross(s - x, t - x)) == 0 && sgn(dot(s - x, t - x)) < 0;}
     40 inline bool onseg(Point x, Line a) { return onseg(x, a.s, a.t);}
     41 
     42 struct Circle {
     43     Point c;
     44     double r;
     45     Circle() {}
     46     Circle(Point c, double r) : c(c), r(r) {}
     47     bool in(Point x) { return sgn(veclen(x - c) - r) <= 0;}
     48     Point point(double x) { return Point(c.x + cos(x) * r, c.y + sin(x) * r);}
     49 } ;
     50 const double R = 10.0;
     51 Circle cake = Circle(Point(0.0, 0.0), R);
     52 const double PI = acos(-1.0);
     53 template<class T> T sqr(T x) { return x * x;}
     54 inline double angle(Point x) { return atan2(x.y, x.x);}
     55 
     56 int clint(Line s, Point *sol) {
     57     Point nor = normal(s.vec()), ip = llint(s, Line(cake.c, cake.c + nor));
     58     double dis = veclen(cake.c - ip);
     59     if (sgn(dis - cake.r) >= 0) return 0;
     60     Point dxy = vecunit(s.vec()) * sqrt(sqr(cake.r) - sqr(dis));
     61     int ret = 0;
     62     sol[ret] = ip + dxy;
     63     if (onseg(sol[ret], s)) ret++;
     64     sol[ret] = ip - dxy;
     65     if (onseg(sol[ret], s)) ret++;
     66     return ret;
     67 }
     68 
     69 double getsec(Point a, Point b) {
     70     double a1 = angle(a - cake.c);
     71     double a2 = angle(b - cake.c);
     72     double da = fabs(a1 - a2);
     73     if (da > PI) da = PI * 2.0 - da;
     74     return sqr(cake.r) * da * sgn(cross(a - cake.c, b - cake.c)) / 2.0;
     75 }
     76 
     77 inline double gettri(Point a, Point b) { return cross(a - cake.c, b - cake.c) / 2.0;}
     78 //typedef vector<Point> VP;
     79 const int N = 111;
     80 struct VP {
     81     Point vex[N];
     82     int n;
     83     void clear() { n = 0;}
     84     void push_back(Point x) { vex[n++] = x;}
     85     void pop_back() { n--;}
     86     int size() { return n;}
     87 } ;
     88 
     89 double cpint(VP pt) {
     90     double ret = 0.0;
     91     int n = pt.size();
     92     Point tmp[2];
     93     pt.vex[n] = pt.vex[0];
     94     for (int i = 0; i < n; i++) {
     95         int ic = clint(Line(pt.vex[i], pt.vex[i + 1]), tmp);
     96         if (ic == 0) {
     97             if (!cake.in(pt.vex[i]) || !cake.in(pt.vex[i + 1])) ret += getsec(pt.vex[i], pt.vex[i + 1]);
     98             else ret += gettri(pt.vex[i], pt.vex[i + 1]);
     99         } else if (ic == 1) {
    100             if (cake.in(pt.vex[i])) ret += gettri(pt.vex[i], tmp[0]), ret += getsec(tmp[0], pt.vex[i + 1]);
    101             else ret += getsec(pt.vex[i], tmp[0]), ret += gettri(tmp[0], pt.vex[i + 1]);
    102         } else {
    103             if (pt.vex[i] < pt.vex[i + 1] ^ tmp[0] < tmp[1]) swap(tmp[0], tmp[1]);
    104             ret += getsec(pt.vex[i], tmp[0]);
    105             ret += gettri(tmp[0], tmp[1]);
    106             ret += getsec(tmp[1], pt.vex[i + 1]);
    107         }
    108 //        cout << "~~ic " << ic << ' ' << ret << endl;
    109     }
    110     return fabs(ret);
    111 }
    112 
    113 bool fixpoly(VP &poly) {
    114     double sum = 0.0;
    115     int n = poly.size();
    116     poly.vex[n] = poly.vex[0];
    117     for (int i = 0; i < n; i++) sum += cross(poly.vex[i], poly.vex[i + 1]);
    118     if (sgn(sum) == 0) return false;
    119     if (sgn(sum) < 0) reverse(poly.vex, poly.vex + n);
    120     return true;
    121 }
    122 
    123 void cutpoly(VP &poly, Line l, VP &ret) {
    124     ret.clear();
    125     int n = poly.size();
    126 //    cout << n << endl;
    127     poly.vex[n] = poly.vex[0];
    128     for (int i = 0; i < n; i++) {
    129         if (sgn(cross(l.vec(), poly.vex[i] - l.s)) >= 0) ret.push_back(poly.vex[i]);
    130         if (sgn(cross(l.vec(), poly.vex[i] - poly.vex[i + 1]))) {
    131             Point ip = llint(l, Line(poly.vex[i], poly.vex[i + 1]));
    132 //            cout << "ip " << ip.x << ' ' << ip.y << endl;
    133             if (onseg(ip, poly.vex[i], poly.vex[i + 1]) || poly.vex[i] == ip) ret.push_back(ip);
    134         }
    135     }
    136 //    cout << "cp sz " << ret.size() << endl;
    137 }
    138 
    139 const int M = 22222;
    140 int q[1111111], qh, qt, nu;
    141 VP rec[M];
    142 queue<int> recycle;
    143 
    144 int getID() {
    145     int ret;
    146     if (nu >= M) {
    147         if (recycle.empty()) { puts("shit!"); while (1) ;}
    148         ret = recycle.front();
    149         recycle.pop();
    150     } else ret = nu++;
    151     return ret;
    152 }
    153 
    154 void retID(int x) { recycle.push(x);}
    155 
    156 int main() {
    157 //    freopen("in", "r", stdin);
    158 //    freopen("out", "w", stdout);
    159     int T, n, tmp;
    160     double x, y;
    161     cin >> T;
    162     while (T-- && cin >> n) {
    163         while (!recycle.empty()) recycle.pop();
    164         qh = qt = nu = 0;
    165         tmp = getID();
    166         rec[tmp].clear();
    167         rec[tmp].push_back(Point(-R * 2.0, -R * 2.0));
    168         rec[tmp].push_back(Point(R * 2.0, -R * 2.0));
    169         rec[tmp].push_back(Point(R * 2.0, R * 2.0));
    170         rec[tmp].push_back(Point(-R * 2.0, R * 2.0));
    171         fixpoly(rec[tmp]);
    172         q[qt++] = tmp;
    173         for (int i = 0; i < n; i++) {
    174             cin >> x >> y;
    175             int sz = qt - qh;
    176             Line t = Line(cake.point(x), cake.point(y));
    177 //            cout << cake.point(x).x << '=' << cake.point(x).y << endl;
    178 //            cout << cake.point(y).x << '~' << cake.point(y).y << endl;
    179             for (int j = 0; j < sz; j++) {
    180                 tmp = getID();
    181 //                cout << "qh ?? " << qh << ' ' << q[qh] << ' ' << rec[q[qh]].size() << endl;
    182                 cutpoly(rec[q[qh]], t, rec[tmp]);
    183                 if (fixpoly(rec[tmp])) {
    184 //                    cout << j << "~~1 " << rec[tmp].size() << endl;
    185 //                    for (int k = 0; k < rec[tmp].size(); k++) cout << rec[tmp].vex[k].x << ' ' << rec[tmp].vex[k].y << endl;
    186                     q[qt++] = tmp;
    187                 }
    188                 swap(t.s, t.t);
    189                 tmp = getID();
    190                 cutpoly(rec[q[qh]], t, rec[tmp]);
    191                 if (fixpoly(rec[tmp])) {
    192 //                    cout << j << "~~2 " << rec[tmp].size() << endl;
    193 //                    for (int k = 0; k < rec[tmp].size(); k++) cout << rec[tmp].vex[k].x << ' ' << rec[tmp].vex[k].y << endl;
    194                     q[qt++] = tmp;
    195                 }
    196                 retID(q[qh++]);
    197             }
    198 //            cout << "sz~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ " << qt - qh << endl;
    199         }
    200         double mx = 0.0;
    201         while (qh < qt) {
    202             mx = max(mx, cpint(rec[q[qh++]]));
    203 //            cout << ".. " << mx << endl;
    204         }
    205         printf("%.2f
    ", mx);
    206     }
    207     return 0;
    208 }
    209 
    210 /*
    211 6
    212 2
    213 -3.140000 0.000000
    214 -1.000000 1.000000
    215 2
    216 -3.141592 0.000000
    217 -1.570796 1.570796
    218 3
    219 -3.000000 3.000000
    220 -2.000000 2.000000
    221 -1.000000 1.000000
    222 4
    223 -3.140000 0.000000
    224 -1.000000 1.000000
    225 -3.140000 -1.000000
    226 1.000000 0.000000
    227 6
    228 -3.140000 0.000000
    229 -1.000000 1.000000
    230 -3.140000 -1.000000
    231 1.000000 0.000000
    232 -3.140000 -1.000000
    233 1.000000 0.000000
    234 6
    235 -3.141592 0.000000
    236 -1.570796 1.570796
    237 -3.141592 -1.570796
    238 0.000000 1.570796
    239 -3.141592 1.570796
    240 0.000000 -1.570796
    241 */
    View Code

     

    PSLG的方法将尽快更新上来!

    UPD:

      模拟遍历边界,985ms压线过,因为有圆弧,所以有几个特判。比较好奇别人那些稳稳的不超时除了少用了STL还做了些什么?

    代码如下:

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <cmath>
      6 #include <vector>
      7 #include <map>
      8 #include <set>
      9 
     10 using namespace std;
     11 
     12 const double EPS = 1e-8;
     13 inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
     14 
     15 struct Point {
     16     double x, y;
     17     int id;
     18     Point() {}
     19     Point(double x, double y) : x(x), y(y) {}
     20     bool operator < (Point a) const { return sgn(x - a.x) < 0 || sgn(x - a.x) == 0 && y < a.y;}
     21     bool operator == (Point a) const { return sgn(x - a.x) == 0 && sgn(y - a.y) == 0;}
     22     Point operator + (Point a) { return Point(x + a.x, y + a.y);}
     23     Point operator - (Point a) { return Point(x - a.x, y - a.y);}
     24     Point operator * (double p) { return Point(x * p, y * p);}
     25     Point operator / (double p) { return Point(x / p, y / p);}
     26 } ;
     27 
     28 inline double cross(Point a, Point b) { return a.x * b.y - a.y * b.x;}
     29 inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y;}
     30 inline double veclen(Point x) { return sqrt(dot(x, x));}
     31 inline Point vecunit(Point x) { return x / veclen(x);}
     32 inline Point normal(Point x) { return Point(-x.y, x.x) / veclen(x);}
     33 
     34 const int N = 111;
     35 Point pts[N * N];
     36 int ptcnt;
     37 
     38 struct Line {
     39     Point s, t;
     40     Line() {}
     41     Line(Point s, Point t) : s(s), t(t) {}
     42     Point vec() { return t - s;}
     43     Point point(double p) { return s + vec() * p;}
     44 } ;
     45 
     46 inline Point llint(Line a, Line b) { return a.point(cross(b.vec(), a.s - b.s) / cross(a.vec(), b.vec()));}
     47 inline bool onseg(Point x, Point a, Point b) { return sgn(cross(a - x, b - x)) == 0 && sgn(dot(a - x, b - x)) <= 0;}
     48 inline bool onseg(Point x, Line l) { return onseg(x, l.s, l.t);}
     49 
     50 const double R = 10.0;
     51 inline bool oncircle(Point x) { return sgn(veclen(x) - R) == 0;}
     52 inline Point getpt(double p) { return Point(cos(p) * R, sin(p) * R);}
     53 inline double angle(Point x) { return atan2(x.y, x.x);}
     54 
     55 struct Node {
     56     double ang;
     57     int id;
     58     bool arc;
     59     Node() {}
     60     Node(double ang, int id) : ang(ang), id(id) { arc = false;}
     61     bool operator < (Node x) const { return sgn(ang - x.ang) < 0 || sgn(ang - x.ang) == 0 && arc > x.arc;}
     62 } ;
     63 Line cut[N];
     64 
     65 const double PI = acos(-1.0);
     66 template<class T> T sqr(T x) { return x * x;}
     67 Point ori, tmp[N << 1];
     68 vector<Node> nb[N * N], oc;
     69 typedef pair<int, int> PII;
     70 typedef pair<int, bool> PIB;
     71 set<PII> used;
     72 map<int, PIB> nx[N * N], anx[N * N];
     73 
     74 
     75 inline double caltri(Point a, Point b) { return cross(a, b) / 2.0;}
     76 double calsec(Point a, Point b) {
     77     double da = atan2(b.y, b.x) - atan2(a.y, a.x);
     78     da += da < 0 ? PI * 2.0 : 0.0;
     79     return sqr(R) * da / 2.0;
     80 }
     81 
     82 int main() {
     83 //    freopen("in", "r", stdin);
     84 //    freopen("out", "w", stdout);
     85     int T, n;
     86     double s, t;
     87     Point ip;
     88     scanf("%d", &T);
     89     while (T-- && ~scanf("%d", &n)) {
     90         ptcnt = 0;
     91         used.clear();
     92         for (int i = 0; i < n; i++) {
     93             scanf("%lf%lf", &s, &t);
     94             cut[i] = Line(getpt(s), getpt(t));
     95             pts[ptcnt++] = getpt(s);
     96             pts[ptcnt++] = getpt(t);
     97             for (int j = 0; j < i; j++) {
     98                 if (sgn(cross(cut[i].vec(), cut[j].vec()))) {
     99                     ip = llint(cut[i], cut[j]);
    100 //                    cout << "ip " << ip.x << ' ' << ip.y << endl;
    101                     if (onseg(ip, cut[i])) pts[ptcnt++] = ip;
    102                 }
    103             }
    104         }
    105 //        cout << "pt " << ptcnt << endl;
    106         sort(pts, pts + ptcnt);
    107         ptcnt = unique(pts, pts + ptcnt) - pts;
    108 //        cout << "npt " << ptcnt << endl;
    109         for (int i = 1; i <= ptcnt; i++) nb[pts[i - 1].id = i].clear(), nx[i].clear(), anx[i].clear();
    110         int ptn;
    111         for (int i = 0; i < n; i++) {
    112             ptn = 0;
    113             for (int j = 1; j <= ptcnt; j++) {
    114                 if (onseg(pts[j - 1], cut[i])) tmp[ptn++] = pts[j - 1];
    115             }
    116             sort(tmp, tmp + ptn);
    117             for (int j = 1; j < ptn; j++) {
    118                 nb[tmp[j].id].push_back(Node(angle(tmp[j - 1] - tmp[j]), tmp[j - 1].id));
    119                 nb[tmp[j - 1].id].push_back(Node(angle(tmp[j] - tmp[j - 1]), tmp[j].id));
    120             }
    121         }
    122         oc.clear();
    123         for (int i = 1; i <= ptcnt; i++) if (oncircle(pts[i - 1])) oc.push_back(Node(angle(pts[i - 1]), i));
    124         sort(oc.begin(), oc.end());
    125 //        for (int i = 0; i < oc.size(); i++) cout << oc[i].id << ' '; cout << endl;
    126         oc.push_back(oc[0]);
    127         for (int i = 1, sz = oc.size(); i < sz; i++) {
    128             nb[oc[i].id].push_back(Node(angle(pts[oc[i - 1].id - 1] - pts[oc[i].id - 1]), oc[i - 1].id));
    129             nb[oc[i].id][nb[oc[i].id].size() - 1].arc = true;
    130             nb[oc[i - 1].id].push_back(Node(angle(pts[oc[i].id - 1] - pts[oc[i - 1].id - 1]), -oc[i].id));
    131             nb[oc[i - 1].id][nb[oc[i - 1].id].size() - 1].arc = true;
    132         }
    133         for (int i = 1; i <= ptcnt; i++) {
    134             sort(nb[i].begin(), nb[i].end());
    135 //            cout << i << " : " << pts[i - 1].x << ' ' << pts[i - 1].y << endl;
    136             nb[i].push_back(nb[i][0]);
    137 //            for (int j = 0; j < nb[i].size(); j++) cout << nb[i][j].id << '-' << nb[i][j].arc << ' '; cout << endl;
    138             for (int j = 1, sz = nb[i].size(); j < sz; j++) {
    139                 if (nb[i][j].id < 0) continue;
    140                 if (nb[i][j].arc) {
    141                     if (nb[i][j - 1].arc) { if (j < nb[i].size() - 1) nx[nb[i][j + 1].id][i] = PIB(abs(nb[i][j - 1].id), true), j++; else nx[nb[i][0].id][i] = PIB(abs(nb[i][j - 1].id), true);}
    142                     else anx[nb[i][j].id][i] = PIB(abs(nb[i][j - 1].id), false);
    143                 } else {
    144                     if (!nb[i][j - 1].arc || nb[i][j - 1].id < 0) nx[nb[i][j].id][i] = PIB(abs(nb[i][j - 1].id), nb[i][j - 1].arc);
    145                 }
    146             }
    147             nb[i].pop_back();
    148         }
    149 //        for (int i = 1; i <= ptcnt; i++) {
    150 //            if (anx[i].size()) cout << anx[i].size() << '~' << (*anx[i].begin()).first << '~' << (*anx[i].begin()).second.first << ' ' << nx[i].size() << endl;
    151 //            else puts("~~~");
    152 //        }
    153         double mx = 0.0, area;
    154         int ls, cur;
    155         PIB tt;
    156         bool arc;
    157         for (int i = 0; i < ptcnt; i++) {
    158             for (int j = 0, sz = nb[i].size(); j < sz; j++) {
    159                 if (nb[i][j].arc) continue;
    160                 ls = i, cur = nb[i][j].id;
    161                 if (used.find(PII(ls, cur)) != used.end()) continue;
    162                 arc = false;
    163                 area = caltri(pts[ls - 1], pts[cur - 1]);
    164                 used.insert(PII(ls, cur));
    165 //                cout << "start " << ls << ' ';
    166                 int cnt = 10;
    167                 while (cur != i && cnt--) {
    168 //                    cout << cur << ' ';
    169                     if (arc) tt = anx[ls][cur];
    170                     else tt = nx[ls][cur];
    171                     ls = cur, cur = tt.first, arc = tt.second;
    172                     if (arc) area += calsec(pts[ls - 1], pts[cur - 1]);
    173                     else area += caltri(pts[ls - 1], pts[cur - 1]), used.insert(PII(ls, cur));
    174                 }
    175 //                cout << area << endl;
    176                 mx = max(mx, fabs(area));
    177             }
    178         }
    179         printf("%.2f
    ", mx);
    180     }
    181     return 0;
    182 }
    View Code

    ——written by Lyon

  • 相关阅读:
    PAT:1069. The Black Hole of Numbers (20) AC
    PAT:1008. Elevator (20) AC
    PAT:1052. Linked List Sorting (25) 部分错误
    PAT:1032. Sharing (25) AC
    PAT:1059. Prime Factors (25) AC
    素数表(筛选法)
    PAT:1048. Find Coins (25)(双指针法) AC
    PAT:1048. Find Coins (25)(二分查找) AC
    iOS 9.0 设置状态栏颜色 和隐藏
    UIPageViewController用法
  • 原文地址:https://www.cnblogs.com/LyonLys/p/poj_3743_Lyon.html
Copyright © 2020-2023  润新知