嘟嘟嘟
大体题意:按顺序给出\(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; }