LightOJ 1313 Protect the Mines (Convex Hull && Minimum Circle)

Jan's LightOJ :: Problem 1313 - Protect the Mines

  wa了好多天的一个凸包啊!之前是想错方向了,以为最后的凸包一定由在起初构建的凸包上的点构成的,于是就狂wa不止。昨天在地铁上面讨论这题,突然想到,对于一个凸包,每一条边都不会穿过要被包围的点集。所以,我们可以先判断有向直线是否穿过要被包围的点集,得到有可能围成凸包的所有有向边。然后用floyd算法,计算最小环的长度。可是,我在打的过程中居然忘记了对于一个点是否能到下一个点的判断是要找出是否能够通过中间任意一个点到达,所以就漏了一个或“|”的符号。于是又wa了一个晚上。

  改过来就过了_(:з」∠)_。。代码如下:

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <cstring>
  5 
  6 using namespace std;
  7 
  8 struct Point {
  9     int x, y;
 10     Point() {}
 11     Point(int x, int y) : x(x), y(y) {}
 12 } ;
 13 Point operator + (Point a, Point b) { return Point(a.x + b.x, a.y + b.y);}
 14 Point operator - (Point a, Point b) { return Point(a.x - b.x, a.y - b.y);}
 15 bool operator < (Point a, Point b) { return a.x < b.x || a.x == b.x < a.y < b.y;}
 16 inline int crossDet(Point a, Point b) { return a.x * b.y - a.y * b.x;}
 17 inline int crossDet(Point o, Point a, Point b) { return crossDet(a - o, b - o);}
 18 inline int dotDet(Point a, Point b) { return a.x * b.x + a.y * b.y;}
 19 
 20 inline bool onSeg(Point p, Point a, Point b) { return crossDet(p, a, b) == 0 && dotDet(a - p, b - p) < 0;}
 21 
 22 int ptInPoly(Point p, Point *poly, int sz) {
 23     int wn = 0;
 24     poly[sz] = poly[0];
 25     for (int i = 0; i < sz; i++) {
 26         if (onSeg(p, poly[i], poly[i + 1])) return -1;
 27         int k = crossDet(poly[i], poly[i + 1], p);
 28         int d1 = poly[i].y - p.y;
 29         int d2 = poly[i + 1].y - p.y;
 30         if (k > 0 && d1 <= 0 && d2 > 0) wn++;
 31         if (k < 0 && d2 <= 0 && d1 > 0) wn--;
 32     }
 33     if (wn != 0) return 1;
 34     return 0;
 35 }
 36 
 37 int andrew(Point *pt, int n, Point *ch) {
 38     int m = 0;
 39     sort(pt, pt + n);
 40     for (int i = 0; i < n; i++) {
 41         while (m > 1 && crossDet(ch[m - 2], ch[m - 1], pt[i]) <= 0) m--;
 42         ch[m++] = pt[i];
 43     }
 44     int k = m;
 45     for (int i = n - 2; i >= 0; i--) {
 46         while (m > k && crossDet(ch[m - 2], ch[m - 1], pt[i]) <= 0) m--;
 47         ch[m++] = pt[i];
 48     }
 49     if (n > 1) m--;
 50     return m;
 51 }
 52 
 53 const int N = 111;
 54 
 55 int inPoly(Point *mines, int m, Point *poly, int p) {
 56     int ret = 0;
 57     for (int i = 0; i < m; i++) {
 58         if (int t = ptInPoly(mines[i], poly, p)) {
 59             if (t == -1) {
 60                 puts("shit!!!");
 61                 while (1) ;
 62             }
 63             mines[ret++] = mines[i];
 64         }
 65     }
 66     return ret;
 67 }
 68 
 69 bool mat[N][N], res[N][N], cur[N][N];
 70 
 71 bool allOnLeft(Point a, Point b, Point *s, int m) {
 72     for (int i = 0; i < m; i++) {
 73         if (crossDet(a, b, s[i]) > 0) return false;
 74     }
 75     return true;
 76 }
 77 
 78 int work(Point *holes, int h, Point *mines, int m) {
 79     memset(mat, 0, sizeof(mat));
 80     memset(res, 0, sizeof(res));
 81     for (int i = 0; i < h; i++) {
 82         for (int j = 0; j < h; j++) {
 83             if (i == j) continue;
 84             if (allOnLeft(holes[i], holes[j], mines, m)) mat[i][j] = res[i][j] = true;
 85         }
 86     }
 87 //    for (int i = 0; i < h; i++) {
 88 //        cout << "holes " << holes[i].x << ' ' << holes[i].y << endl;
 89 //    }
 90 //    for (int i = 0; i < m; i++) {
 91 //        cout << "mines " << mines[i].x << ' ' << mines[i].y << endl;
 92 //    }
 93 //    for (int i = 0; i < h; i++) {
 94 //        for (int j = 0; j < h; j++) {
 95 //            cout << mat[i][j];
 96 //        }
 97 //        cout << endl;
 98 //    }
 99 //    cout << "check" << endl;
100     for (int t = 1; t <= h; t++) {
101         for (int i = 0; i < h; i++) {
102             if (res[i][i]) {
103 //                cout << i << endl;
104                 return t;
105             }
106             for (int j = 0; j < h; j++) {
107                 cur[i][j] = res[i][j];
108             }
109         }
110         memset(res, 0, sizeof(res));
111         for (int i = 0; i < h; i++) {
112             for (int k = 0; k < h; k++) {
113                 if (cur[i][k]) {
114                     for (int j = 0; j < h; j++) {
115                         res[i][j] |= cur[i][k] & mat[k][j];
116                     }
117                 }
118             }
119         }
120     }
121     puts("damn!");
122     while (1) ;
123     return 0;
124 }
125 
126 int main() {
127 //    freopen("in", "r", stdin);
128     int T, n, m, g, p;
129     Point holes[N], mines[N], poly[N];
130     cin >> T;
131     for (int cas = 1; cas <= T; cas++) {
132         cin >> n >> m >> g >> p;
133         for (int i = 0; i < n; i++) cin >> holes[i].x >> holes[i].y;
134         for (int i = 0; i < m; i++) cin >> mines[i].x >> mines[i].y;
135         int t = andrew(holes, n, poly);
136 //        cout << "Convex Hull" << endl;
137         int k = inPoly(mines, m, poly, t);
138 //        cout << "inPoly" << endl;
139         int ans1 = (m - k) * g;
140         t = k ? work(holes, n, mines, k) : 0;
141         int ans2 = t * p;
142 //        cout << ans1 << ' ' << ans2 << endl;
143         cout << "Case " << cas << ": " << ans1 + ans2 << endl;
144     }
145     return 0;
146 }
View Code

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/LOJ_1313_Lyon.html