题目链接:http://poj.org/problem?id=2588
Snakes
Description
Buffalo Bill wishes to cross a 1000x1000 square field. A number of snakes are on the field at various positions, and each snake can strike a particular distance in any direction. Can Bill make the trip without being bitten?
Input
Assume that the southwest corner of the field is at (0,0) and the northwest corner at (0,1000). The input consists of a line containing n <= 1000, the number of snakes. A line follows for each snake, containing three real numbers: the (x,y) location of the snake and its strike distance. The snake will bite anything that passes closer than this distance from its location.
Output
Bill must enter the field somewhere between the southwest and northwest corner and must leave somewhere between the southeast and northeast corners.
If Bill can complete the trip, give coordinates at which he may enter and leave the field. If Bill may enter and leave at several places, give the most northerly. If there is no such pair of positions, print "Bill will be bitten." Sample Input 3 500 500 499 0 0 999 1000 1000 200 Sample Output Bill enters at (0.00, 1000.00) and leaves at (1000.00, 800.00). Source |
1 #include<iostream> 2 #include<cmath> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 #define maxn 1005 7 8 /*-------------上下左右边界判断-------------*/ 9 struct UpDown{ 10 double x, y, area; 11 }snack[maxn]; 12 struct LeftRight{ 13 double up, down; 14 int i; 15 }le[maxn], ri[maxn]; 16 17 18 int father[maxn], map[maxn][maxn]; 19 20 21 //----------检查当前出入最高点是否可用-------------------- 22 bool check(LeftRight *p, double x, int n){ 23 for (int i = 0; i < n; i++){ 24 if (p[i].up>x&&p[i].down < x) 25 return false; 26 } 27 return true; 28 } 29 30 //-------------并查集判断构造的点(包括上下边界)是否连通------------------- 31 int getf(int x){ 32 return father[x] != x ? father[x] = getf(father[x]) : x; 33 } 34 35 36 int main() 37 { 38 int n, i, j; 39 while (cin >> n){ 40 for (i = 0; i <= n + 1; i++) 41 father[i] = i; 42 int L = 0, R = 0; 43 memset(map, 0, sizeof(map)); 44 for (i = 1; i <= n; i++){ 45 cin >> snack[i].x >> snack[i].y >> snack[i].area; 46 47 //-----------建立上下关系--------------- 48 if (snack[i].y + snack[i].area > 1000) 49 map[0][i] = map[i][0] = 1; 50 if (snack[i].y - snack[i].area < 0) 51 map[n + 1][i] = map[i][n + 1] = 1; 52 53 //---------建立左右关系------------------ 54 if (snack[i].x - snack[i].area < 0){ 55 le[L].up = snack[i].y + sqrt(pow(snack[i].area, 2) - pow(snack[i].x, 2)); 56 le[L].down = snack[i].y - sqrt(pow(snack[i].area, 2) - pow(snack[i].x, 2)); 57 le[L++].i = i; 58 } 59 if (snack[i].x + snack[i].area >1000){ 60 ri[R].up = snack[i].y + sqrt(pow(snack[i].area, 2) - pow((1000 - snack[i].x), 2)); 61 ri[R].down = snack[i].y - sqrt(pow(snack[i].area, 2) - pow((1000 - snack[i].x), 2)); 62 ri[R++].i = i; 63 } 64 } 65 66 //-------------通过圆心判断各区域相交情况------------------- 67 for (i = 1; i < n; i++) 68 for (j = i + 1; j <= n; j++){ 69 if (snack[i].area + snack[j].area>sqrt(pow((snack[i].x - snack[j].x), 2) + pow((snack[i].y - snack[j].y), 2))) 70 map[i][j] = map[j][i] = 1; 71 } 72 73 //-----------并查集处理------------------ 74 for (i = 0; i <= n; i++) 75 for (j = i + 1; j <= n + 1; j++){ 76 if (map[i][j]){ 77 int x = getf(i), y = getf(j); 78 if (x != y) 79 father[y] = x; 80 } 81 } 82 83 84 85 if (getf(n + 1) == getf(0)) 86 cout << "Bill will be bitten." << endl; 87 88 else{ 89 double Lflag = -1, Rflag = -1, Lup = 1000, Ldown = 0, Rup = 1000, Rdown = 0; 90 91 //-----------找到最高可用左边界------------------------ 92 for (i = 0; i < L; i++){ 93 if (getf(le[i].i) == getf(0) && le[i].down < Lup) 94 Lup = le[i].down; 95 if (getf(le[i].i) == getf(n + 1) && le[i].up >Ldown) 96 Ldown = le[i].up; 97 } 98 99 if (check(le, 1000, L) && Lup == 1000) 100 Lflag = 1000; 101 102 for (i = 0; i < L; i++){ 103 if (le[i].up <= Lup&&le[i].up >= Ldown&&check(le, le[i].up, L) && Lflag < le[i].up) 104 Lflag = le[i].up; 105 if (le[i].down <= Lup&&le[i].down >= Ldown&&check(le, le[i].down, L) && Lflag < le[i].down) 106 Lflag = le[i].down; 107 } 108 //---------------------------------------------------------------------- 109 110 111 //--------------------------===右边界处理----------------------- 112 for (i = 0; i < R; i++){ 113 if (getf(ri[i].i) == getf(0) && ri[i].down < Rup) 114 Rup = ri[i].down; 115 if (getf(ri[i].i) == getf(n + 1) && ri[i].up >Rdown) 116 Rdown = ri[i].up; 117 } 118 if (check(ri, 1000, R) && Rup == 1000) 119 Rflag = 1000; 120 for (i = 0; i < R; i++){ 121 if (ri[i].up <= Rup&&ri[i].up >= Rdown&&check(ri, ri[i].up, R) && Rflag < ri[i].up) 122 Rflag = ri[i].up; 123 if (ri[i].down <= Rup&&ri[i].down >= Rdown&&check(ri, ri[i].down, R) && Rflag < ri[i].down) 124 Rflag = ri[i].down; 125 } 126 if (L == 0) 127 Lflag = 1000; 128 if (R == 0) 129 Rflag = 1000; 130 if (Rflag < 0 || Lflag < 0) 131 cout << "Bill will be bitten." << endl; 132 else 133 printf("Bill enters at (0.00, %.2lf) and leaves at (1000.00, %.2lf).\n", Lflag, Rflag); 134 } 135 } 136 return 0; 137 }