• HIT Summer Day17 计算几何初步 题解


    ABC题意及解法见课件。这里附上代码。

    A:POJ 2318

     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <iomanip>
    16 #include <cctype>
    17 #include <cassert>
    18 #include <bitset>
    19 #include <ctime>
    20 
    21 using namespace std;
    22 
    23 #define pau system("pause")
    24 #define ll long long
    25 #define pii pair<int, int>
    26 #define pb push_back
    27 #define mp make_pair
    28 #define clr(a, x) memset(a, x, sizeof(a))
    29 
    30 const double pi = acos(-1.0);
    31 const int INF = 0x3f3f3f3f;
    32 const int MOD = 1e9 + 7;
    33 const double EPS = 1e-9;
    34 
    35 struct point {
    36     int x, y;
    37     point () {}
    38     point (int x, int y) : x(x), y(y) {}
    39     void input() {
    40         scanf("%d%d", &x, &y);
    41     }
    42 };
    43 struct segment {
    44     point p1, p2;
    45     segment () {}
    46     segment (point p1, point p2) : p1(p1), p2(p2) {}
    47     void input() {
    48         p1.input();
    49         p2.input();
    50     }
    51 } seg[5015];
    52 double cross_mul(point p1, point p2, point p3) {
    53     return (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y);
    54 }
    55 bool ok(segment s, point p) {
    56     return cross_mul(s.p1, s.p2, p) < 0;
    57 }
    58 int n, m, x_left, x_right, y_up, y_down, is_first = 1, cnt[5015];
    59 int main() {
    60     while (~scanf("%d", &n) && n) {
    61         scanf("%d%d%d%d%d", &m, &x_left, &y_up, &x_right, &y_down);
    62         seg[0] = segment(point(x_left, y_down), point(x_left, y_up));
    63         for (int i = 1; i <= n; ++i) {
    64             int u, l;
    65             scanf("%d%d", &u, &l);
    66             seg[i] = segment(point(l, y_down), point(u, y_up));
    67         }
    68         clr(cnt, 0);
    69         for (int i = 1; i <= m; ++i) {
    70             int x, y;
    71             scanf("%d%d", &x, &y);
    72             int l = 0, r = n, mi, res;
    73             while (l <= r) {
    74                 mi = l + r >> 1;
    75                 if (ok(seg[mi], point(x, y))) {
    76                     l = (res = mi) + 1;
    77                 } else {
    78                     r = mi - 1;
    79                 }
    80             }
    81             ++cnt[res];
    82         }
    83         if (is_first) {
    84             is_first = 0;
    85         } else {
    86             puts("");
    87         }
    88         for (int i = 0; i <= n; ++i) {
    89             printf("%d: %d
    ", i, cnt[i]);
    90         }
    91     }
    92     return 0;
    93 }
    View Code

    B: POJ 3304

     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <iomanip>
    16 #include <cctype>
    17 #include <cassert>
    18 #include <bitset>
    19 #include <ctime>
    20 
    21 using namespace std;
    22 
    23 #define pau system("pause")
    24 #define ll long long
    25 #define pii pair<int, int>
    26 #define pb push_back
    27 #define mp make_pair
    28 #define clr(a, x) memset(a, x, sizeof(a))
    29 
    30 const double pi = acos(-1.0);
    31 const int INF = 0x3f3f3f3f;
    32 const int MOD = 1e9 + 7;
    33 const double EPS = 1e-8;
    34 
    35 int T, n;
    36 struct point {
    37     double x, y;
    38     point () {}
    39     point (double x, double y) : x(x), y(y) {}
    40     void input() {
    41         scanf("%lf%lf", &x, &y);
    42     }
    43     double dis(point p) {
    44         return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
    45     }
    46 };
    47 struct seg {
    48     point p1, p2;
    49     seg () {}
    50     seg (point p1, point p2) : p1(p1), p2(p2) {}
    51     void input() {
    52         p1.input();
    53         p2.input();
    54     }
    55 } s[105];
    56 double cross_mul(point p1, point p2, point p3) {
    57     return (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y);
    58 }
    59 bool cross(point pa, point pb, seg l) {
    60     point p1 = l.p1, p2 = l.p2;
    61     return cross_mul(pa, pb, p1) * cross_mul(pa, pb, p2) <= EPS;
    62 }
    63 bool solve(point p1, point p2) {
    64     if (p1.dis(p2) <= EPS) return false;
    65     for (int i = 1; i <= n; ++i) {
    66         if (!cross(p1, p2, s[i])) {
    67             return false;
    68         }
    69     }
    70     return true;
    71 }
    72 int main() {
    73     scanf("%d", &T);
    74     while (T--) {
    75         scanf("%d", &n);
    76         for (int i = 1; i <= n; ++i) {
    77             s[i].input();
    78         }
    79         bool ans = 0;
    80         if (1 == n) ans = 1;
    81         for (int i = 1; i < n; ++i) {
    82             point p1 = s[i].p1, p2 = s[i].p2;
    83             for (int j = i + 1; j <= n; ++j) {
    84                 point p3 = s[j].p1, p4 = s[j].p2;
    85                 if (solve(p1, p3) || solve(p1, p4) || solve(p2, p3) || solve(p2, p4)) {
    86                     ans = 1;
    87                 }
    88             }
    89         }
    90         puts(ans ? "Yes!" : "No!");
    91     }
    92     return 0;
    93 }
    View Code

    C: POJ 1127

      1 #include <iostream>
      2 #include <fstream>
      3 #include <sstream>
      4 #include <cstdlib>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <queue>
     11 #include <stack>
     12 #include <vector>
     13 #include <set>
     14 #include <map>
     15 #include <iomanip>
     16 #include <cctype>
     17 #include <cassert>
     18 #include <bitset>
     19 #include <ctime>
     20 
     21 using namespace std;
     22 
     23 #define pau system("pause")
     24 #define ll long long
     25 #define pii pair<int, int>
     26 #define pb push_back
     27 #define mp make_pair
     28 #define clr(a, x) memset(a, x, sizeof(a))
     29 
     30 const double pi = acos(-1.0);
     31 const int INF = 0x3f3f3f3f;
     32 const int MOD = 1e9 + 7;
     33 const double EPS = 1e-6;
     34 
     35 struct point {
     36     int x, y;
     37     point () {}
     38     point (int x, int y) : x(x), y(y) {}
     39     point operator - (const point &p) const {
     40         return point(x - p.x, y - p.y);}
     41 };
     42 struct seg {
     43     point p1, p2;
     44     seg () {}
     45     seg (point p1, point p2) : p1(p1), p2(p2) {}
     46 };
     47 int cross_mul(point p1, point p2) {
     48     return p1.x * p2.y - p1.y * p2.x;
     49 }
     50 bool between(point a, point b, point c) {// a between b and c
     51     return (a.x - b.x) * (a.x - c.x) <= 0 && (a.y - b.y) * (a.y - c.y) <= 0;
     52 }
     53 bool cross(seg l1, seg l2) {
     54     int res1 = cross_mul(l1.p2 - l1.p1, l2.p1 - l1.p1);
     55     int res2 = cross_mul(l1.p2 - l1.p1, l2.p2 - l1.p1);
     56     int res3 = cross_mul(l2.p2 - l2.p1, l1.p1 - l2.p1);
     57     int res4 = cross_mul(l2.p2 - l2.p1, l1.p2 - l2.p1);
     58     if (!(res1 | res2 | res3 | res4)) {
     59         return between(l1.p1, l2.p1, l2.p2) || between(l1.p2, l2.p1, l2.p2) || 
     60                between(l2.p1, l1.p1, l1.p2) || between(l2.p2, l1.p1, l1.p2);
     61     }
     62     return res1 * res2 <= 0 && res3 * res4 <= 0;
     63 }
     64 int Rank[15], parent[15], n;
     65 void ini() {
     66     for (int i = 1; i <= n; ++i) {
     67         Rank[i] = 1;
     68         parent[i] = i;
     69     }
     70 }
     71 int Find(int x) {return x == parent[x] ? x : parent[x] = Find(parent[x]);}
     72 void uni(int x, int y) {
     73     x = Find(x), y = Find(y);
     74     if (x == y) return;
     75 
     76     if (Rank[x] < Rank[y]) {
     77         parent[x] = y;
     78     } else {
     79         parent[y] = x;
     80         if (Rank[x] == Rank[y]) ++Rank[x];
     81     }
     82 }
     83 seg s[15];
     84 int main() {
     85     while (~scanf("%d", &n) && n) {
     86         for (int i = 1; i <= n; ++i) {
     87             scanf("%d%d%d%d", &s[i].p1.x, &s[i].p1.y, &s[i].p2.x, &s[i].p2.y);
     88         }
     89         ini();
     90         for (int i = 1; i <= n; ++i) {
     91             for (int j = i + 1; j <= n; ++j) {
     92                 if (cross(s[i], s[j])) uni(i, j);
     93             }
     94         }
     95         int x, y;
     96         while (~scanf("%d%d", &x, &y) && x && y) {
     97             puts(Find(x) == Find(y) ? "CONNECTED" : "NOT CONNECTED");
     98         }
     99     }
    100     return 0;
    101 }
    View Code

    D: POJ 1696

    题意:

    一只蚂蚁只能向左走或直走,且不能经过之前走过的路径,问路径最多能覆盖多少个点。

    思路:

    每次选择蚂蚁左边未走过的最靠右的点。实际上,未走过的点永远在蚂蚁的左边;且蚂蚁的路径不会和之前有交点。这两条性质都可以类数学归纳法证明。这样便会遍历到所有的点。

    因此,每次贪心选以上一个位置为极点,极角最小的点。

      1 #include <iostream>
      2 #include <fstream>
      3 #include <sstream>
      4 #include <cstdlib>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <queue>
     11 #include <stack>
     12 #include <vector>
     13 #include <set>
     14 #include <map>
     15 #include <list>
     16 #include <iomanip>
     17 #include <cctype>
     18 #include <cassert>
     19 #include <bitset>
     20 #include <ctime>
     21 
     22 using namespace std;
     23 
     24 #define pau system("pause")
     25 #define ll long long
     26 #define pii pair<int, int>
     27 #define pb push_back
     28 #define mp make_pair
     29 #define clr(a, x) memset(a, x, sizeof(a))
     30 
     31 const double pi = acos(-1.0);
     32 const int INF = 0x3f3f3f3f;
     33 const int MOD = 1e9 + 7;
     34 const double EPS = 1e-9;
     35 
     36 /*
     37 #include <ext/pb_ds/assoc_container.hpp>
     38 #include <ext/pb_ds/tree_policy.hpp>
     39 
     40 using namespace __gnu_pbds;
     41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
     42 */
     43 
     44 struct Point {
     45     int x, y;
     46     Point () {}
     47     Point (int x, int y) : x(x), y(y) {}
     48     ll operator ^ (const Point &p) const {
     49         return x * p.y - y * p.x;
     50     }
     51     Point operator - (const Point &p) const {
     52         return Point(x - p.x, y - p.y);
     53     }
     54     bool operator == (const Point &p) const {
     55         return x == p.x && y == p.y;
     56     }
     57     bool operator < (const Point &p) const {
     58         return y == p.y ? x < p.x : y < p.y;
     59     }
     60     void input() {
     61         scanf("%d", &x);
     62         scanf("%d%d", &x, &y);
     63     }
     64     void output() {
     65         printf("%d %d
    ", x, y);
     66     }
     67     double dis(const Point &p) const {
     68         return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
     69     }
     70 } p[1015], pp;
     71 bool cmp(const Point &p1, const Point &p2) {
     72     ll v = (p1 - pp) ^ (p2 - pp);
     73     if (v) return v > 0;
     74     return abs(p1.x - pp.x) + abs(p1.y - pp.y) < abs(p2.x - pp.x) + abs(p2.y - pp.y);
     75 }
     76 int cross(Point pp, Point p1, Point p2) {
     77     return ((p1 - pp) ^ (p2 - pp)) > 0;
     78 }
     79 int T, n, vis[55];
     80 vector<int> vec;
     81 int main() {
     82     scanf("%d", &T);
     83     while (T--) {
     84         scanf("%d", &n);
     85         for (int i = 1; i <= n; ++i) {
     86             p[i].input();
     87             vis[i] = 0;
     88         }
     89         pp = p[1]; int id = 1;
     90         for (int i = 2; i <= n; ++i) {
     91             if (p[i] < pp) {
     92                 pp = p[i];
     93                 id = i;
     94             }
     95         }
     96         vec.clear();
     97         vis[id] = 1; vec.pb(id);
     98         for (int i = 1; i < n; ++i) {
     99             int j = 1;
    100             for (; j <= n; ++j) {
    101                 if (!vis[j]) {
    102                     id = j;
    103                     break;
    104                 }
    105             }
    106             for (++j; j <= n; ++j) {
    107                 if (vis[j]) continue;
    108                 if (cmp(p[j], p[id])) {
    109                     id = j;
    110                 }
    111             }
    112             vis[id] = 1; vec.pb(id);
    113             pp = p[id];
    114         }
    115         printf("%d", n);
    116         for (int i = 0; i < vec.size(); ++i) {
    117             printf(" %d", vec[i]);
    118         }
    119         puts("");
    120     }
    121     return 0;
    122 }
    View Code

    E: HDU 1705

    题意:对一个整点三角形,问内部有多少整点。

    思路:求出面积S,对于边(x1, y1), (x2, y2),其上的整点数为gcd(abs(x1 - x2), abs(y1 - y2))。如此累计便得出边上整点数s。 n = S - s / 2 + 1.

     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <list>
    16 #include <iomanip>
    17 #include <cctype>
    18 #include <cassert>
    19 #include <bitset>
    20 #include <ctime>
    21 
    22 using namespace std;
    23 
    24 #define pau system("pause")
    25 #define ll long long
    26 #define pii pair<int, int>
    27 #define pb push_back
    28 #define mp make_pair
    29 #define clr(a, x) memset(a, x, sizeof(a))
    30 
    31 const double pi = acos(-1.0);
    32 const int INF = 0x3f3f3f3f;
    33 const int MOD = 1e9 + 7;
    34 const double EPS = 1e-9;
    35 
    36 /*
    37 #include <ext/pb_ds/assoc_container.hpp>
    38 #include <ext/pb_ds/tree_policy.hpp>
    39 
    40 using namespace __gnu_pbds;
    41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
    42 */
    43 
    44 int x[3], y[3];
    45 int main() {
    46     while (1) {
    47         int flag = 0;
    48         for (int i = 0; i < 3; ++i) {
    49             scanf("%d%d", &x[i], &y[i]);
    50             if (x[i] || y[i]) flag = 1;
    51         }
    52         if (!flag) break;
    53         int S = abs((x[1] - x[0]) * (y[2] - y[0]) - (x[2] - x[0]) * (y[1] - y[0])) / 2;
    54         ll s = 0;
    55         for (int i = 0; i < 3; ++i) {
    56             s += __gcd(abs(x[(i + 1) % 3] - x[i]), abs(y[(i + 1) % 3] - y[i]));
    57         }
    58         printf("%d
    ", S + 1 - s / 2);
    59     }
    60     return 0;
    61 }
    View Code

    F: HDU 1756

    题意: 判断一个点是否在多边形内部。

    思路:先判断是否在边上。再点射法求出水平射线与下降端点和边的相交次数和。为奇数在内部,为偶数在外部。

      1 #include <iostream>
      2 #include <fstream>
      3 #include <sstream>
      4 #include <cstdlib>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <queue>
     11 #include <stack>
     12 #include <vector>
     13 #include <set>
     14 #include <map>
     15 #include <list>
     16 #include <iomanip>
     17 #include <cctype>
     18 #include <cassert>
     19 #include <bitset>
     20 #include <ctime>
     21 
     22 using namespace std;
     23 
     24 #define pau system("pause")
     25 #define ll long long
     26 #define pii pair<int, int>
     27 #define pb push_back
     28 #define mp make_pair
     29 #define clr(a, x) memset(a, x, sizeof(a))
     30 
     31 const double pi = acos(-1.0);
     32 const int INF = 0x3f3f3f3f;
     33 const int MOD = 1e9 + 7;
     34 const double EPS = 1e-9;
     35 
     36 /*
     37 #include <ext/pb_ds/assoc_container.hpp>
     38 #include <ext/pb_ds/tree_policy.hpp>
     39 
     40 using namespace __gnu_pbds;
     41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
     42 */
     43 
     44 int n, m;
     45 struct Point {
     46     int x, y, cnt_down;
     47     Point () {}
     48     Point (int _x, int _y) {
     49         x = _x, y = _y, cnt_down = 0;
     50     }
     51     Point operator - (const Point &p) const {
     52         return Point(x - p.x, y - p.y);
     53     }
     54     ll operator ^ (const Point &p) const {
     55         return x * p.y - y * p.x;
     56     }
     57     void input() {
     58         scanf("%d%d", &x, &y);
     59         cnt_down = 0;
     60     }
     61 } p[105];
     62 struct Seg {
     63     Point s, e;
     64     Seg () {}
     65     Seg (Point s, Point e) : s(s), e(e) {}
     66     bool cross(const Seg &seg) const {
     67         return ((s - seg.s) ^ (seg.e - seg.s)) * ((e - seg.s) ^ (seg.e - seg.s)) < 0;
     68     }
     69 };
     70 bool between(Point p, Seg seg) {
     71     if ((p - seg.s) ^ (seg.e - seg.s)) return false;
     72     return (p.x - seg.s.x) * (p.x - seg.e.x) <= 0 && (p.y - seg.s.y) * (p.y - seg.e.y) <= 0;
     73 }
     74 int main() {
     75     while (~scanf("%d", &n)) {
     76         for (int i = 1; i <= n; ++i) {
     77             p[i].input();
     78         }
     79         for (int i = 1; i <= n; ++i) {
     80             int j = i % n + 1;
     81             if (p[i].y < p[j].y) ++p[i].cnt_down;
     82             else if (p[j].y < p[i].y) ++p[j].cnt_down;
     83         }
     84         scanf("%d", &m);
     85         while (m--) {
     86             Point pp; pp.input();
     87             int f = 0;
     88             for (int i = 1; i <= n; ++i) {
     89                 if (between(pp, Seg(p[i], p[i % n + 1]))) {
     90                     f = 1;
     91                     break;
     92                 }
     93             }
     94             if (f) {
     95                 puts("Yes");
     96                 continue;
     97             }
     98             Seg ss = Seg(pp, Point(1001, pp.y));
     99             int cnt = 0;
    100             for (int i = 1; i <= n; ++i) {
    101                 if (between(p[i], ss)) cnt += p[i].cnt_down;
    102             }
    103             for (int i = 1; i <= n; ++i) {
    104                 if (ss.cross(Seg(p[i], p[i % n + 1])) && Seg(p[i], p[i % n + 1]).cross(ss)) ++cnt;
    105             }
    106             puts(cnt & 1 ? "Yes" : "No");
    107         }
    108     }
    109     return 0;
    110 }
    View Code

    G: POJ 1556

    题意:矩形内n组墙,每组墙由中间两块空隙构成。问从起点到终点不撞墙的最短距离。

    思路:最短路径的所有线段端点一定都是原来墙的端点。于是对于第i组墙的第j个点,枚举所有转移到他上的端点,判断两点连线是否撞墙。如不撞墙,更新dp值。最终dp[n + 1][1]即为所求。

    复杂度O(n^3).

      1 #include <iostream>
      2 #include <fstream>
      3 #include <sstream>
      4 #include <cstdlib>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <queue>
     11 #include <stack>
     12 #include <vector>
     13 #include <set>
     14 #include <map>
     15 #include <list>
     16 #include <iomanip>
     17 #include <cctype>
     18 #include <cassert>
     19 #include <bitset>
     20 #include <ctime>
     21 
     22 using namespace std;
     23 
     24 #define pau system("pause")
     25 #define ll long long
     26 #define pii pair<int, int>
     27 #define pb push_back
     28 #define mp make_pair
     29 #define clr(a, x) memset(a, x, sizeof(a))
     30 
     31 const double pi = acos(-1.0);
     32 const int INF = 0x3f3f3f3f;
     33 const int MOD = 1e9 + 7;
     34 const double EPS = 1e-9;
     35 
     36 /*
     37 #include <ext/pb_ds/assoc_container.hpp>
     38 #include <ext/pb_ds/tree_policy.hpp>
     39 
     40 using namespace __gnu_pbds;
     41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
     42 */
     43 
     44 struct Point {
     45     double x, y;
     46     Point () {}
     47     Point (double x, double y) : x(x), y(y) {}
     48     double operator ^ (const Point &p) const {
     49         return x * p.y - y * p.x;
     50     }
     51     Point operator - (const Point &p) const {
     52         return Point(x - p.x, y - p.y);
     53     }
     54     bool operator == (const Point &p) const {
     55         return x == p.x && y == p.y;
     56     }
     57     bool operator < (const Point &p) const {
     58         return y == p.y ? x < p.x : y < p.y;
     59     }
     60     void input() {
     61         scanf("%d", &x);
     62         scanf("%d%d", &x, &y);
     63     }
     64     void output() {
     65         printf("%d %d
    ", x, y);
     66     }
     67     double dis(const Point &p) const {
     68         return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
     69     }
     70 } p[13][5], pp;
     71 bool cmp(const Point &p1, const Point &p2) {
     72     ll v = (p1 - pp) ^ (p2 - pp);
     73     if (v) return v > 0;
     74     return abs(p1.x - pp.x) + abs(p1.y - pp.y) < abs(p2.x - pp.x) + abs(p2.y - pp.y);
     75 }
     76 int cross(Point pp, Point p1, Point p2) {
     77     return ((p1 - pp) ^ (p2 - pp)) > EPS;
     78 }
     79 struct Seg {
     80     Point s, e;
     81     Seg () {}
     82     Seg (Point s, Point e) : s(s), e(e) {}
     83     bool cross(Point p1, Point p2) {
     84         return ((p2 - p1) ^ (s - p1)) * ((p2 - p1) ^ (e - p1)) < EPS;
     85     }
     86 } ss[23][5];
     87 bool cross_Seg(Seg s1, Seg s2) {
     88     return s1.cross(s2.s, s2.e) && s2.cross(s1.s, s1.e);
     89 }
     90 int n, cnt[23];
     91 double dp[23][5];
     92 int main() {
     93     while (~scanf("%d", &n) && ~n) {
     94         for (int i = 1; i <= n; ++i) {
     95             double x, y;
     96             scanf("%lf", &x);
     97             for (int j = 1; j <= 4; ++j) {
     98                 scanf("%lf", &y);
     99                 p[i][j] = Point(x, y);
    100             }
    101             cnt[i] = 4;
    102             ss[i][1] = Seg(Point(x, 0), p[i][1]);
    103             ss[i][2] = Seg(p[i][2], p[i][3]);
    104             ss[i][3] = Seg(p[i][4], Point(x, 10));
    105         }
    106         cnt[0] = cnt[n + 1] = 1;
    107         p[0][1] = Point(0, 5);
    108         p[n + 1][1] = Point(10, 5);
    109         dp[0][1] = 0;
    110         for (int i = 1; i <= n + 1; ++i) {
    111             for (int j = 1; j <= cnt[i]; ++j) {
    112                 dp[i][j] = INF;
    113             }
    114         }
    115         for (int i = 1; i <= n + 1; ++i) {
    116             for (int j = 1; j <= cnt[i]; ++j) {
    117                 for (int k = 0; k < i; ++k) {
    118                     for (int l = 1; l <= cnt[k]; ++l) {
    119                         Seg ts = Seg(p[i][j], p[k][l]);
    120                         int f = 1;
    121                         for (int o = k + 1; o < i; ++o) {
    122                             for (int _ = 1; _ <= 3; ++_) {
    123                                 if (cross_Seg(ts, ss[o][_])) {
    124                                     f = 0;
    125                                     break;
    126                                 }
    127                             }
    128                         }
    129                         if (f) {
    130                             dp[i][j] = min(dp[i][j], dp[k][l] + p[i][j].dis(p[k][l]));
    131                         }
    132                     }
    133                 }
    134             }
    135         }
    136         printf("%.2f
    ", dp[n + 1][1]);
    137     }
    138     return 0;
    139 }
    View Code

    H: POJ 1113

    题意:对于一个多边形,要筑一个围墙,使多边形上每个点到墙的距离都不超过L。求围墙最短长度。

    思路:实际距离就是凸包长度加上一个半径为l的圆的周长。套凸包板子即可。

      1 #include <iostream>
      2 #include <fstream>
      3 #include <sstream>
      4 #include <cstdlib>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <queue>
     11 #include <stack>
     12 #include <vector>
     13 #include <set>
     14 #include <map>
     15 #include <list>
     16 #include <iomanip>
     17 #include <cctype>
     18 #include <cassert>
     19 #include <bitset>
     20 #include <ctime>
     21 
     22 using namespace std;
     23 
     24 #define pau system("pause")
     25 #define ll long long
     26 #define pii pair<int, int>
     27 #define pb push_back
     28 #define mp make_pair
     29 #define clr(a, x) memset(a, x, sizeof(a))
     30 
     31 const double pi = acos(-1.0);
     32 const int INF = 0x3f3f3f3f;
     33 const int MOD = 1e9 + 7;
     34 const double EPS = 1e-9;
     35 
     36 /*
     37 #include <ext/pb_ds/assoc_container.hpp>
     38 #include <ext/pb_ds/tree_policy.hpp>
     39 
     40 using namespace __gnu_pbds;
     41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
     42 */
     43 
     44 struct Point {
     45     int x, y;
     46     Point () {}
     47     Point (int x, int y) : x(x), y(y) {}
     48     ll operator ^ (const Point &p) const {
     49         return x * p.y - y * p.x;
     50     }
     51     Point operator - (const Point &p) const {
     52         return Point(x - p.x, y - p.y);
     53     }
     54     bool operator == (const Point &p) const {
     55         return x == p.x && y == p.y;
     56     }
     57     bool operator < (const Point &p) const {
     58         return y == p.y ? x < p.x : y < p.y;
     59     }
     60     void input() {
     61         scanf("%d%d", &x, &y);
     62     }
     63     void output() {
     64         printf("%d %d
    ", x, y);
     65     }
     66     double dis(const Point &p) const {
     67         return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
     68     }
     69 } p[1015], pp;
     70 bool cmp(const Point &p1, const Point &p2) {
     71     if (pp == p1) return true;
     72     if (pp == p2) return false;
     73     ll v = (p1 - pp) ^ (p2 - pp);
     74     if (v) return v > 0;
     75     return abs(p1.x - pp.x) + abs(p1.y - pp.y) < abs(p2.x - pp.x) + abs(p2.y - pp.y);
     76 }
     77 int n, l;
     78 stack<Point> sta;
     79 vector<Point> vec;
     80 int main() {
     81     scanf("%d%d", &n, &l);
     82     for (int i = 1; i <= n; ++i) {
     83         p[i].input();
     84     }
     85     pp = p[1];
     86     for (int i = 2; i <= n; ++i) {
     87         if (p[i] < pp) {
     88             pp = p[i];
     89         }
     90     }
     91     sort(p + 1, p + n + 1, cmp);
     92     sta.push(p[1]), sta.push(p[2]);
     93     for (int i = 3; i <= n; ++i) {
     94         while (sta.size() > 1) {
     95             Point p1 = sta.top(); sta.pop();
     96             Point p2 = sta.top(); 
     97             if (((p[i] - p2) ^ (p1 - p2)) < 0) {
     98                 sta.push(p1);
     99                 break;
    100             }
    101         }
    102         sta.push(p[i]);
    103     }
    104     while (sta.size()) {
    105         vec.pb(sta.top()); sta.pop();
    106     }
    107     for (int i = (int)vec.size() - 1; ~i; --i) {
    108         //vec[i].output();
    109     }
    110     double ans = 0;
    111     for (int i = 0; i < vec.size(); ++i) {
    112         int j = (i + 1) % vec.size();
    113         ans += vec[i].dis(vec[j]);
    114     }
    115     ans += 2 * pi * l;
    116     printf("%.0f
    ", ans);    
    117     return 0;
    118 }
    View Code

    I:POJ 2653

    思路:注意到在顶部的线段小于1000.于是我们每次加入线段时,扫一遍所有在顶部的线段,如果相交,那他就不再是顶部了,从这个集合中删去。可以用链表维护这个东西。复杂度O(1000n)。

     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <list>
    16 #include <iomanip>
    17 #include <cctype>
    18 #include <cassert>
    19 #include <bitset>
    20 #include <ctime>
    21 
    22 using namespace std;
    23 
    24 #define pau system("pause")
    25 #define ll long long
    26 #define pii pair<int, int>
    27 #define pb push_back
    28 #define mp make_pair
    29 #define clr(a, x) memset(a, x, sizeof(a))
    30 
    31 const double pi = acos(-1.0);
    32 const int INF = 0x3f3f3f3f;
    33 const int MOD = 1e9 + 7;
    34 const double EPS = 1e-9;
    35 
    36 struct point {
    37     double x, y;
    38     point () {}
    39     point (double x, double y) : x(x), y(y) {}
    40     void input() {
    41         scanf("%lf%lf", &x, &y);
    42     }
    43 };
    44 struct segment {
    45     point p1, p2;
    46     segment () {}
    47     segment (point p1, point p2) : p1(p1), p2(p2) {}
    48     void input() {
    49         p1.input();
    50         p2.input();
    51     }
    52 } seg[100015];
    53 double cross_mul(point p1, point p2, point p3) {
    54     return (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y);
    55 }
    56 bool cross(segment s1, segment s2) {
    57     return cross_mul(s1.p1, s1.p2, s2.p1) * cross_mul(s1.p1, s1.p2, s2.p2) <= EPS && 
    58            cross_mul(s2.p1, s2.p2, s1.p1) * cross_mul(s2.p1, s2.p2, s1.p2) <= EPS;
    59 }
    60 list<int> ans;
    61 int n;
    62 int main() {
    63     while (~scanf("%d", &n) && n) {
    64         ans.clear();
    65         for (int i = 1; i <= n; ++i) {
    66             seg[i].input();
    67             for (list<int>::iterator it = ans.begin(); it != ans.end();) {
    68                 int x = *it;
    69                 if (cross(seg[x], seg[i])) {
    70                     ans.erase(it++);
    71                 } else {
    72                     ++it;
    73                 }
    74             }
    75             ans.pb(i);
    76         }
    77         printf("Top sticks:");
    78         for (list<int>::iterator it = ans.begin(); it != ans.end();) {
    79             printf(" %d", *it);
    80             putchar(++it == ans.end() ? '.' : ',');
    81         }
    82         puts("");
    83     }
    84     return 0;
    85 }
    View Code

    J:HDU 6325

    题意:求字典序最小上凸包。

    思路:选最左边的点,按x排序正常跑凸包的基础上注意两点:

    位置相同的点直接取id小的

    凸包上共线的点中间的点选或不选由线上的后继点的id大小决定。比较大小进行取舍。

      1 #include <iostream>
      2 #include <fstream>
      3 #include <sstream>
      4 #include <cstdlib>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <queue>
     11 #include <stack>
     12 #include <vector>
     13 #include <set>
     14 #include <map>
     15 #include <list>
     16 #include <iomanip>
     17 #include <cctype>
     18 #include <cassert>
     19 #include <bitset>
     20 #include <ctime>
     21 
     22 using namespace std;
     23 
     24 #define pau system("pause")
     25 #define ll long long
     26 #define pii pair<int, int>
     27 #define pb push_back
     28 #define mp make_pair
     29 #define clr(a, x) memset(a, x, sizeof(a))
     30 
     31 const double pi = acos(-1.0);
     32 const int INF = 0x3f3f3f3f;
     33 const int MOD = 1e9 + 7;
     34 const double EPS = 1e-9;
     35 
     36 /*
     37 #include <ext/pb_ds/assoc_container.hpp>
     38 #include <ext/pb_ds/tree_policy.hpp>
     39 
     40 using namespace __gnu_pbds;
     41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
     42 */
     43 
     44 struct Point {
     45     ll x, y;
     46     int id;
     47     Point () {}
     48     Point (int x, int y) : x(x), y(y) {}
     49     ll operator ^ (const Point &p) const {
     50         return x * p.y - y * p.x;
     51     }
     52     Point operator - (const Point &p) const {
     53         return Point(x - p.x, y - p.y);
     54     }
     55     bool operator == (const Point &p) const {
     56         return x == p.x && y == p.y;
     57     }
     58     bool operator < (const Point &p) const {
     59         return x == p.x ? id > p.id : x < p.x;
     60     }
     61     void input(int i) {
     62         id = i;
     63         scanf("%lld%lld", &x, &y);
     64     }
     65     void output() {
     66         printf("%lld %lld
    ", x, y);
     67     }
     68     double dis(const Point &p) const {
     69         return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
     70     }
     71 } p[200015], pp;
     72 ll cross(Point pp, Point p1, Point p2) {
     73     return ((p1 - pp) ^ (p2 - pp));
     74 }
     75 int T, n;
     76 deque<int> que;
     77 int main() {
     78     scanf("%d", &T);
     79     while (T--) {
     80         scanf("%d", &n);
     81         for (int i = 1; i <= n; ++i) {
     82             p[i].input(i);
     83         }
     84         sort(p + 1, p + n + 1);
     85         que.pb(1), que.pb(2);
     86         for (int i = 3; i <= n; ++i) {
     87             while (que.size() > 1) {
     88                 int x = que.back(); que.pop_back();
     89                 if (p[x] == p[i]) continue;
     90                 int y = que.back();
     91                 ll v = cross(p[y], p[i], p[x]);
     92                 if (v < 0) continue;
     93                 if (!v && p[i].id < p[x].id) continue;
     94                 que.pb(x);
     95                 break;
     96             }
     97             que.pb(i);
     98         }
     99         printf("1"); que.pop_front();
    100         while (que.size()) {
    101             printf(" %d", p[que.front()].id); que.pop_front();
    102         }
    103         puts("");
    104     }
    105     return 0;
    106 }
    View Code

    K:CodeForces - 603D

    题意:平面上n个线,形成一坨交点,问多少个三角形外接圆经过圆心。

    思路:等价于圆心向所有直线做垂足,问多少个三元垂足对共线。

    额外注意double可能丢精度,用两个整数存有理数。

     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <iomanip>
    16 #include <cctype>
    17 #include <cassert>
    18 #include <bitset>
    19 #include <ctime>
    20 
    21 using namespace std;
    22 
    23 #define pau system("pause")
    24 #define ll long long
    25 #define pll pair<ll, ll>
    26 #define pb push_back
    27 #define mp make_pair
    28 #define clr(a, x) memset(a, x, sizeof(a))
    29 
    30 const double pi = acos(-1.0);
    31 const int INF = 0x3f3f3f3f;
    32 const int MOD = 1e9 + 7;
    33 const double EPS = 1e-9;
    34 
    35 int n, a[2015], b[2015], c[2015];
    36 ll px[2015], qx[2015], py[2015], qy[2015], rx, ry;
    37 ll gcd(ll x, ll y) {while (y) y ^= x ^= y ^= x %= y; return x;}
    38 int flag;
    39 map<pll, int> mmp;
    40 ll ans = 0;
    41 int main() {
    42     scanf("%d", &n);
    43     for (int i = 1; i <= n; ++i) {
    44         scanf("%d%d%d", &a[i], &b[i], &c[i]);
    45         if (!c[i]) ++flag;
    46         px[i] = (ll)a[i] * c[i], py[i] = (ll)b[i] * c[i];
    47         qx[i] = qy[i] = (ll)a[i] * a[i] + (ll)b[i] * b[i];
    48     }
    49     for (int i = 1; i <= n; ++i) {
    50         if (!c[i]) continue;
    51         mmp.clear();
    52         for (int j = 1; j < i; ++j) {
    53             if (!c[j]) continue;
    54             rx = px[i] * qx[j] - px[j] * qx[i];
    55             ry = py[i] * qy[j] - py[j] * qy[i];
    56             ll g = gcd(rx, ry);
    57             //printf("rx = %lld, ry = %lld, g = %lld
    ", rx, ry, g);
    58             rx /= g, ry /= g;
    59             if (rx < 0 || !rx && ry < 0) {
    60                 rx = -rx;
    61                 ry = -ry;
    62             }
    63             ++mmp[pll(rx, ry)];
    64         }
    65         for (map<pll, int>::iterator it = mmp.begin(); it != mmp.end(); ++it) {
    66             ll x = (*it).second;
    67             ans += x * (x - 1) >> 1;
    68         }
    69     }
    70     if (2 == flag) ans += n - 2;
    71     printf("%I64d
    ", ans);
    72     return 0;
    73 }
    View Code

    L:CodeForces - 975E 

    题意:先不说了...

    思路:我们只需维护重心位置以及每个点相对重心的关系。然后每次操作暴力模拟。码量较大。

      1 #include <iostream>
      2 #include <fstream>
      3 #include <sstream>
      4 #include <cstdlib>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <queue>
     11 #include <stack>
     12 #include <vector>
     13 #include <set>
     14 #include <map>
     15 #include <list>
     16 #include <iomanip>
     17 #include <cctype>
     18 #include <cassert>
     19 #include <bitset>
     20 #include <ctime>
     21 
     22 using namespace std;
     23 
     24 #define pau system("pause")
     25 #define ll long long
     26 #define pii pair<int, int>
     27 #define pb push_back
     28 #define mp make_pair
     29 #define clr(a, x) memset(a, x, sizeof(a))
     30 
     31 const long double pi = acos(-1.0);
     32 const int INF = 0x3f3f3f3f;
     33 const int MOD = 1e9 + 7;
     34 const long double EPS = 1e-9;
     35 
     36 /*
     37 #include <ext/pb_ds/assoc_container.hpp>
     38 #include <ext/pb_ds/tree_policy.hpp>
     39 
     40 using namespace __gnu_pbds;
     41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
     42 */
     43 
     44 int n, q;
     45 struct point {
     46     long double x, y;
     47     point() {}
     48     point (long double x, long double y) : x(x), y(y) {}
     49     void input() {
     50         //scanf("%lf%lf", &x, &y);
     51         cin >> x >> y;
     52     }
     53     void output() {
     54         double tx = x, ty = y;
     55         printf("%.12f %.12f
    ", tx, ty);
     56     }
     57     point operator - (const point &p) const {
     58         return point(x - p.x, y - p.y);
     59     }
     60     point operator + (const point &p) const {
     61         return point(x + p.x, y + p.y);
     62     }
     63     long double operator ^ (const point &p) const {
     64         return x * p.y - y * p.x;
     65     }
     66     point operator / (const long double &k) const {
     67         return point(x / k, y / k);
     68     }
     69     point operator * (const long double &k) const {
     70         return point(x * k, y * k);
     71     }
     72     long double dis(const point &p) const {
     73         return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
     74     }
     75 } p[100015];
     76 long double d0[100015], d1[100015], th[100015];
     77 long double cal_th(point p1, point p0, point p2) {
     78     long double th1 = atan2(p1.y - p0.y, p1.x - p0.x);
     79     long double th2 = atan2(p2.y - p0.y, p2.x - p0.x);
     80     long double res = th1 - th2;
     81     if (res < 0) res += 2 * pi;
     82     return res;
     83 }
     84 multiset<int> rem;
     85 point get_pos(int index) {
     86     long double th1 = atan2(p[1].y - p[0].y, p[1].x - p[0].x);
     87     long double th2 = th1 - th[index];
     88     if (th2 < 0) th2 += 2 * pi;
     89     return p[0] + point(d0[index] * cos(th2), d0[index] * sin(th2));
     90 }
     91 void rot_and_update(int index2) {
     92     point p2 = get_pos(index2);
     93     long double th01 = atan2(p[0].y - p2.y, p[0].x - p2.x);
     94     long double th02 = 3 * pi / 2;
     95     long double th0 = th02 - th01;
     96     if (th0 < 0) th0 += 2 * pi;
     97     long double th11 = atan2(p[1].y - p2.y, p[1].x - p2.x);
     98     //p[0].output(), p[1].output(), p2.output();
     99     long double th12 = th11 + th0;
    100     if (2 * pi <= th12) th12 -= 2 * pi;
    101     //printf("index2 = %d
    ", index2);
    102     p[0] = point(p2.x, p2.y - d0[index2]);
    103     p[1] = p2 + point(d1[index2] * cos(th12), d1[index2] * sin(th12));
    104 }
    105 void get_wp() {
    106     long double s = 0;
    107     p[0] = point(0, 0);
    108     for (int i = 2; i < n; ++i) {
    109         long double ts = (p[i] - p[1]) ^ (p[i] - p[i + 1]);
    110         p[0] = p[0] + (p[1] + p[i] + p[i + 1]) / 3 * ts;
    111         s += ts;
    112     }
    113     p[0] = p[0] / s;
    114 }
    115 int main() {
    116     scanf("%d%d", &n, &q);
    117     p[0] = point(0, 0);
    118     for (int i = 1; i <= n; ++i) {
    119         p[i].input();
    120     }
    121     get_wp();
    122     for (int i = 1; i <= n; ++i) {
    123         th[i] = cal_th(p[1], p[0], p[i]);
    124         d0[i] = p[0].dis(p[i]);
    125         d1[i] = p[1].dis(p[i]);
    126     }
    127     rem.insert(1), rem.insert(2);
    128     while (q--) {
    129         int op;
    130         scanf("%d", &op);
    131         if (1 == op) {
    132             int f, t;
    133             scanf("%d%d", &f, &t);
    134             multiset<int>::iterator it = rem.lower_bound(f);
    135             rem.erase(it);
    136             int v = *rem.begin();
    137             rot_and_update(v);
    138             rem.insert(t);
    139         } else {
    140             int v;
    141             scanf("%d", &v);
    142             get_pos(v).output();
    143         }
    144     }
    145     return 0;
    146 }
    147 /*
    148 10 10
    149 0 -100000000
    150 1 -100000000
    151 1566 -99999999
    152 2088 -99999997
    153 2610 -99999994
    154 3132 -99999990
    155 3654 -99999985
    156 4176 -99999979
    157 4698 -99999972
    158 5220 -99999964
    159 1 2 5
    160 2 1
    161 1 1 7
    162 2 5
    163 1 5 4
    164 1 4 2
    165 2 8
    166 1 7 9
    167 2 1
    168 1 2 10
    169 */
    View Code
  • 相关阅读:
    sublime 设置侧边栏颜色
    laravel 连接mongodb
    PHP empty(),isset()与is_null()的实例测试
    ubuntu 14.04 64位安装 深度截图
    ubuntu 14.04 64位安装 lightworks (解决libtiff4依赖)
    ubuntu LAMP 配置
    一个查询大学英语四六级的类
    jstree 权限树 简单教程
    对接ebay,订单系统开发
    常用的PHP判断 检测 函数.
  • 原文地址:https://www.cnblogs.com/BIGTOM/p/9512099.html
Copyright © 2020-2023  润新知