【POJ 1039】Pipe
【题目描述】 有个管子,有 n 个转折点,管子宽度为 1 ,问有没有一条直线能够穿过这个管子,如果不能,问最远能够到达哪里,输出照到的点的横坐标
【题目思路】我们可以想到,这个光线能够穿过管子的极限情况是,擦着一个下底面点和一个上顶面点,所以我们只需要枚举下面的点和上面的点连成的直线,判断其是否能够穿过所有管子
注意:
1.判断光线是否穿过管子当前的转折点,可以判断这条直线是不是和这个管子那个转折点的上下点组成的线段相切
2.最开始没有想明白,就直接枚举,以后要想清楚
1 #include<cstdio> 2 #include<algorithm> 3 #define ll double 4 using namespace std; 5 const int MAXN = 510; 6 const double eps = 1e-3; 7 struct P 8 { 9 ll x, y; 10 P(ll a=0,ll b=0):x(a),y(b){} 11 P operator-(P a) { return P(x - a.x, y - a.y); } 12 P operator+(P a) { return P(x + a.x, y + a.y); } 13 ll operator^(P a) { return a.y*x - a.x*y; } 14 ll operator*(P a) { return a.x*x + a.y*y; } 15 }up[MAXN],down[MAXN]; 16 struct L 17 { 18 P s, t; 19 L() {}; 20 L(P a, P b) :s(a), t(b) {} 21 }up_L[MAXN],down_L[MAXN]; 22 int sgn(double x) 23 { 24 if (x > eps) return 1; 25 if (x < -eps) return -1; 26 return 0; 27 } 28 ll cross(P a, P b) 29 { 30 return a ^ b; 31 } 32 ll cross(P a, P b, P c) 33 { 34 return (a - c) ^ (b - c); 35 } 36 int L_is_inter(L a, L b) 37 { 38 return sgn(cross(b.s, a.s, a.t))*sgn(cross(b.t, a.s, a.t)); 39 } 40 bool S_is_inter(L a, L b) 41 { 42 return sgn((a.s - a.t) ^ (b.s - b.t)) == 0; 43 } 44 P get_inter(L a, L b) 45 { 46 return a.s + (a.t - a.s)*(cross(b.t - b.s, a.s - b.s)) / cross(a.t - a.s, b.t - b.s); 47 } 48 int main() 49 { 50 int n=1; 51 while (1) 52 { 53 scanf("%d", &n);if (n==0) break; 54 for (int i = 1; i <= n; i++) 55 { 56 double x, y; 57 scanf("%lf %lf ", &x, &y); 58 up[i] = P(x, y); 59 down[i] = P(x, y - 1); 60 if (i == 1) continue; 61 up_L[i] = L(up[i - 1], up[i]); 62 down_L[i] = L(down[i - 1], down[i]); 63 } 64 ll ans = -10000000000.0; 65 P tmp; 66 bool flag = 0; 67 for (int i = 1; i <= n; i++) 68 { 69 for (int j = 1; j <= n; j++) 70 { 71 if (i == j) continue; 72 L t = L(down[i], up[j]); 73 int k; 74 for ( k = 1; k <= n; k++) 75 { 76 L line = L(down[k], up[k]); 77 bool ret = (L_is_inter(t, line)<=0); 78 if (k == 1) 79 { 80 if (ret) 81 continue; 82 else 83 { 84 break; 85 } 86 } 87 if (!ret) 88 { 89 line = L(up[k - 1], up[k]); 90 if (L_is_inter(t, line)<0) 91 { 92 tmp = get_inter(t, line); 93 //printf("i==%d j==%d k=%d tmp==%lf\n", i, j, k, tmp.x); 94 ans = max(ans, tmp.x); 95 } 96 line = L(down[k - 1], down[k]); 97 if (L_is_inter(t, line)<0) 98 { 99 100 tmp = get_inter(t, line); 101 //printf("i==%d j==%d k=%d tmp==%lf\n", i, j, k, tmp.x); 102 ans = max(ans, tmp.x); 103 } 104 break; 105 } 106 } 107 if (k > n) { flag = 1; break; } 108 } 109 if (flag) break; 110 } 111 if (flag) { printf("Through all the pipe.\n"); } 112 else 113 printf("%.2f\n", ans); 114 } 115 return 0; 116 }