嘟嘟嘟
大體題意:按順序給出\(n\)個拐點表示一個管道,注意這些點是管道的上端點,下端點是對應的\((x_i, y_i - 1)\)。從管道口射進一束光,問能達到最遠的位置的橫座標。若穿過管道,輸出\(Through\) \(all\) \(the\) $ pipe.$
仍是線段求交問題。ios
枚舉端點做爲直線(光束)上的兩個點。而後判斷這條直線和每一條線段\((x_i, y_i)(x_i, y_i - 1)\)是否有交點。若無,則求出最遠能到達的\(x\)。git
注意座標可爲負,因此剛開始的極小值爲\(-INF\),而不是\(0\)。spa
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<cstdlib> #include<cctype> #include<vector> #include<stack> #include<queue> using namespace std; #define enter puts("") #define space putchar(' ') #define Mem(a, x) memset(a, x, sizeof(a)) #define rg register typedef long long ll; typedef double db; const int INF = 0x3f3f3f3f; const db eps = 1e-8; const int maxn = 25; inline ll read() { ll ans = 0; char ch = getchar(), last = ' '; while(!isdigit(ch)) last = ch, ch = getchar(); while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); if(last == '-') ans = -ans; return ans; } inline void write(ll x) { if(x < 0) x = -x, putchar('-'); if(x >= 10) write(x / 10); putchar(x % 10 + '0'); } int n; struct Vec { db x, y; db operator * (const Vec& oth)const { return x * oth.y - oth.x * y; } }; struct Point { db x, y; Vec operator - (const Point& oth)const { return (Vec){x - oth.x, y - oth.y}; } }a[maxn], b[maxn]; db calc(Point A, Point B, Point C, Point D) { Vec AB = B - A, AC = C - A, AD = D - A, CD = D - C; db s1 = fabs(AB * AC), s2 = fabs(AB * AD); return C.x + CD.x / (s1 + s2) * s1; } db solve(Point A, Point B) { Vec AB = B - A; for(int i = 1; i <= n; ++i) { Vec AC = a[i] - A, AD = b[i] - A; if((AC * AB) * (AD * AB) > eps) { if(i == 1) return -INF; Vec AE = a[i - 1] - A; if((AE * AB) * (AC * AB) < -eps) return calc(A, B, a[i - 1], a[i]); Vec AF = b[i - 1] - A; if((AF * AB) * (AD * AB) < -eps) return calc(A, B, b[i - 1], b[i]); return -INF; } } return INF; } int main() { while(scanf("%d", &n) && n) { for(int i = 1; i <= n; ++i) scanf("%lf%lf", &a[i].x, &a[i].y), b[i].x = a[i].x, b[i].y = a[i].y - 1; db ans = -INF; for(int i = 1; i < n && ans != INF; ++i) { for(int j = i + 1; j <= n; ++j) { ans = max(ans, solve(a[i], a[j])); if(ans == INF) break; ans = max(ans, solve(a[i], b[j])); if(ans == INF) break; ans = max(ans, solve(b[i], a[j])); if(ans == INF) break; ans = max(ans, solve(b[i], b[j])); if(ans == INF) break; } } if(ans == INF) puts("Through all the pipe."); else printf("%.2f\n", ans); } return 0; }