Link: http://poj.org/problem? Id = 1039 http://acm.hust.edu.cn/vjudge/contest/view.action? Cid = 22013 # Problem/bpipe
Time limit:1000 ms |
|
Memory limit:10000 K |
Total submissions:8350 |
|
Accepted:2501 |
Description
The GX light pipeline company started to prepare bent pipes for the new transgalactic light pipeline. during the design phase of the new pipe shape the company ran into the problem of determining how far the light can reach inside each component of the pipe.
Note that the material which the pipe is made from is not transparent and not light reflecting.
Each pipe component consists of specified straight pipes connected tightly together. for the programming purposes, the company developed the description of each component as a sequence of points [x1; Y1], [X2; y2],..., [XN; YN], where X1 <X2 <... XN. these
Are the upper points of the pipe contour. the bottom points of the pipe contour consist of points with Y-coordinate decreased by 1. to each upper point [XI; Yi] there is a corresponding bottom point [XI; (yi)-1] (see picture above ). the company wants to find,
For each pipe component, the point with maximal X-coordinate that the light will reach. the light is emitted by a segment source with endpoints [x1; (Y1)-1] and [x1; Y1] (endpoints are emitting light too ). assume that the light is not bent at the pipe bent
Points and the bent points do not stop the light beam.
Input
The input file contains several blocks each describing one pipe component. each block starts with the number of Bent points 2 <= n <= 20 on separate line. each of the next n lines contains a pair of real values Xi, Yi separated by space. the last block is denoted
With n = 0.
Output
The output file contains lines corresponding to blocks in input file. to each block in the input file there is one line in the output file. each such line contains either a real value, written with precision of two decimal places, or the message through all
The pipe .. the real value is the desired maximal X-coordinate of the point where the light can reach from the source for corresponding pipe component. if this value equals to XN, then the message through all the pipe. will appear in the output file.
Sample Input
40 12 24 16 460 12 -0.65 -4.457 -5.5712 -10.817 -16.550
Sample output
4.67Through all the pipe.
Source
Central Europe 1995
Question:
I will give you a pipe and ask if such a light can pass through from left to right.
If it fails to pass completely, the farthest intersection is output [x maximum]
Algorithm: intersection of a straight line and a line segment [cross product]
Idea: enumerate the upper and lower endpoints into the straight line where the light is located.
Check whether it is legal. If it is legal: then check whether it can pass the entire channel.
If it fails, the farthest X is output.
Note:
When determining the intersection between a line segment and a straight line, you cannot directly use the product of two cross products to determine
[It is possible that the light has been running out of the pipe, and you have no point of intersection,
The final result is that the light passes through the entire channel, but this is not the case]
Therefore, the light and the baffle must be in a straight line between the upper and lower endpoints to determine that the light is indeed in the pipe.
Incorrect ideas:
Start to think about the line and the line segment is only possible, then directly use the product of the cross product to determine whether the line and the line segment are intersection, the red arrow represents the line AB, the three black lines represent the relationship between all the lines and the line AB. [the line can be extended, so it doesn't matter if you draw a line]
In general, it would be better to directly use the code that intersection a straight line and a line segment.
/** Cross Product */double cross (point a, point B) {return. x * B. y-. y * B. x;}/** segment L1 cross line L2 */bool segmentcrossline (line L1, line l2) // segment L1 cross line L2 {return cross (l1.s-l2.s, l2.e-l2.s) * Cross (l2.e-l2.s, l1.e-l2.s)> 0 ;}
However, this naked judgment cannot determine the following situation. If the light runs out of the pipeline from the beginning, there will never be intersection points, if it is placed in the code that I started to connect to the sample, it will directly output
Through all the pipe.
However, this is not the case...
So how to solve:
Method 1:
Like the second code, [kuangbin] first checks whether it is in line with the baffle plate. [that is, determines whether the light is outside the pipe.] Try to make the light and the baffle plate intersect.
If the light produced by the endpoint of the current traversal is the same as that of the front baffle [green part], the light is valid. If a valid light is also the same as that of the back baffle, then the light can pass through the channel behind it, that is, if the light can pass through all the light, if not, it will find the non-Intersecting baffle plate. It can be seen from above or below to find the intersection point, update the farthest x
Method 2:
I learned from my blog that I am still a god, but kb gave me an analysis of the above, so I figured out how to separate the line segments above the pipeline from those below the pipeline. If the light passes through this pipe, the above line segment must be above the light, the cross product between the light and the above line segments will not be <0, so the following line segments must be under the light, the cross product between the light and the following line segments will not be greater than 0 [the cross product mentioned above mainly depends on the direction of traversal in your program]
Refer to blog:
KB God
Still god
/*************************************** * ******************** Baccepted192 kb47 MSC ++ 2744 B Question: let's give you a pipe and ask if such a line of light can pass from left to right completely. If it cannot pass through completely, output the farthest intersection [x largest] algorithm: intersection of a straight line and a line segment [cross product] idea: enumerate the upper and lower endpoints into the line where the light is located to see if it is legal, if it is legal: Then let's see if it can pass through the entire Channel if it cannot pass, output the farthest x Note: When determining the intersection between a line segment and a straight line, you cannot directly use the product of two cross products to determine [it is possible that the light has long been outside the pipeline, the final result is that the light passes through the entire channel, but this is not the case, the light and the bezel must be in a straight line between the upper and lower endpoints, to determine whether the light is in the pipe ********************************* ************************ * *****/# Include <stdio. h> # include <math. h ># include <algorithm> using namespace STD; const int maxn = 30; const double DNF = 100000000; int N; double ans; struct point {Double X, Y; point () {} Point (double _ x, double _ y) {x = _ x; y = _ y;} point operator + (const point & B) const {return point (x + B. x, Y + B. y);} point operator-(const point & B) const {return point (x-B.x, y-B.y);} point operator * (const Dou Ble & P) const {return point (p * X, p * Y);} bool operator = (const point & B) const {return x = B. X & Y = B. Y ;}} up [maxn], down [maxn]; typedef point vector; double cross (point a, point B) {return. x * B. y-. y * B. x;}/** calculates the intersection of a straight line P + TV and a straight line Q + TW */point getlineintersection (point P, vector V, point Q, vector W) {vector u = P-Q; Double T = cross (W, u)/Cross (V, W); Return P + V * t ;} /** precision judgment */const double EPS = 1e-5; int DCMP (Double X) {If (FABS (x) <EPS) return 0; else return x <0? -1: 1;}/** check the line AB. The current light is determined in section E */bool check (point a, point B, int e) {int Sign = 0; int I; for (I = 1; I <n; I ++) {If (DCMP (B-A, up [I]-)) <0 | DCMP (Cross (B-A, up [I + 1]-A) <0) {// determine whether a line AB and a line segment up [I] -- up [I + 1] Intersection [note] Sign = 1; break;} If (DCMP (Cross (B-A, down [I]-A)> 0 | DCMP (B-A, down [I + 1]-A)> 0) {// determine whether a line AB and a line segment go down [I] -- down [I + 1] intersection. [note] Sign = 2; break ;}} if (I <E) Return False; // The light is invalid if (I = N) return true; // obtain the farthest X point interpoint through the entire channel; If (Sign = 1) // intersection with the line segments above the pipeline {interpoint = getlineintersection (A, A-B, up [I], up [I]-up [I + 1]);} else if (Sign = 2) // intersection with a line segment under the pipeline {interpoint = getlineintersection (A, A-B, down [I], down [I]-down [I + 1]);} // If (interpoint = up [N] | interpoint = down [N]) return true; ans = max (ANS, interpoint. x); Return false;} int main () {While (SCAN F ("% d", & N )! = EOF) {If (n = 0) break; Double X, Y; For (INT I = 1; I <= N; I ++) {scanf ("% lf", & X, & Y); up [I] = point (x, y); down [I] = point (X, y-1);} ans =-DNF; int flag = 0; // indicates whether the entire channel can pass if (n <3) Flag = 1; for (INT I = 1; I <= N &&! Flag; I ++) {for (Int J = I + 1; j <= N; j ++) {flag = check (up [I], down [J], i); If (FLAG) break; flag = check (down [I], up [J], I); If (FLAG) break ;} if (FLAG) printf ("through all the pipe. \ n "); else printf (" %. 2lf \ n ", ANS);} return 0 ;}
Kuangbin's code [first checks whether it is in line with the baffle plate, determines whether the light is in the pipe, and then directly calculates with the line segment and straight line intersection]
Http://www.cnblogs.com/kuangbin/p/3192590.html
# Include <iostream> # include <stdio. h> # include <string. h> # include <algorithm> # include <queue> # include <map> # include <vector> # include <set> # include <string> # include <math. h> using namespace STD; const double EPS = 1e-8; int SGN (Double X) {If (FABS (x) <EPS) return 0; If (x <0) return-1; else return 1;} struct point {Double X, Y; point () {} Point (double _ x, double _ y) {x = _ x; y = _ y;} point operator-(const point & B) const {return point (X-B. x, Y-B. y);} // Cross Product double operator ^ (const point & B) const {return x * B. y-y * B. x;} // dot product double operator * (const point & B) const {return x * B. X + Y * B. Y ;}void input () {scanf ("% lf", & X, & Y) ;}; struct line {point S, E; line () {} line (point _ s, point _ e) {S = _ s; E = _ E ;} // calculates the intersection of two straight lines. // if the first value is 0, the line is overlapped. If the value is 1, the line is parallel. If the value is 0, the line is intersecting, 2 is the intersection. // The intersection is meaningful when the first value is 2. Pair <int, point> operator & (const line & B) const {point res = s; if (SGN (S-e) ^ (B. s-b.e) = 0) {If (SGN (s-b.e) ^ (B. s-b.e) = 0) return make_pair (0, Res); // coincidence else return make_pair (1, Res); // parallel} double T = (s-b.s) ^ (B. s-b.e)/(S-e) ^ (B. s-b.e); Res. X + = (E. x-s.x) * t; Res. Y + = (E. y-s.y) * t; return make_pair (2, Res) ;}}; // determine the line and line segment intersection bool seg_inter_line (line L1, line l2) // determine whether the L1 and L2 segments of a straight line intersect. {return SGN (l2.s-l1.e) ^ (l1.s-l1.e) * SGN (l2.e-l1.e) ^ (l1.s-l1.e) <= 0;} Point up [100], down [100]; int main () {int N; while (scanf ("% d ", & n) = 1 & N) {for (INT I = 0; I <n; I ++) {up [I]. input (); down [I] = up [I]; down [I]. y-= 1;} bool flag = false; // pass through all the tags double ans =-10000000.0; int K; For (INT I = 0; I <N; I ++) {for (Int J = I + 1; j <n; j ++) {// determine whether a straight line is up [I] -- down [J] For (k = 0; k <n; k ++) // determine whether the line is outside the pipe, it should intersection all front bezel if (seg_inter_line (line (up [I], down [J]), line (up [K], down [k]) = false) break; If (k> = N) // when all the bezel is passed, the light can penetrate the pipe {flag = true; break ;} if (k> MAX (I, j) // if the light is valid {If (seg_inter_line (line (up [I], down [J]), line (up [k-1], up [k]) {pair <int, point> Pr = line (up [I], down [J]) & line (up [k-1], up [k]); point P = Pr. second; ans = max (ANS, P. x);} If (seg_inter_line (line (up [I], down [J]), line (down [k-1], down [k]) {pair <int, point> Pr = line (up [I], down [J]) & line (down [k-1], down [k]); point P = Pr. second; ans = max (ANS, P. x) ;}} // determines whether a straight line goes down [I] -- up [J] For (k = 0; k <n; k ++) if (seg_inter_line (line (down [I], up [J]), line (up [K], down [k]) = false) break; if (k> = N) {flag = true; break;} If (k> MAX (I, j) {If (seg_inter_line (line (down [I], up [J], line (up [k-1], up [k]) {pair <int, point> Pr = line (down [I], up [J]) & line (up [k-1], up [k]); point P = Pr. second; ans = max (ANS, P. x);} If (seg_inter_line (line (down [I], up [J]), line (down [k-1], down [k]) {pair <int, point> Pr = line (down [I], up [J]) & line (down [k-1], down [k]); point P = Pr. second; ans = max (ANS, P. x) ;}} if (FLAG) break;} If (FLAG) printf ("through all the pipe. \ n "); else printf (" %. 2lf \ n ", ANS);} return 0 ;}