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 }
——written by Lyon