POJ 1039——计算几何初步(判断线段与直线相交)
此题太恶心了。。。。。(开始的时候思路错了,没有考虑到交点可能是拐点,这是其一。其二,就是精度。。。。。。。尼玛啊,这个害我WA了N次)
唉~~~~~精度很重要啊。
还有一点就是先判断枚举的直线是否合理,即是否在管道内。
然后对于每个拐点映射到直线上的Y值是否在管道里,不是则求出X值。
接下来枚举就行。
View Code
1 #include<iostream>
2 #include<cstdio>
3 #define EPS 1e-8
4 using namespace std;
5
6 struct point {
7 double x, y;
8 point(double _x, double _y):x(_x),y(_y){};
9 point(){};
10 point(point &temp)
11 {
12 x = temp.x;
13 y = temp.y;
14 }
15 }pipe[20][2];
16
17 double cross(point &p, point &q)
18 {
19 return q.y*p.x - q.x*p.y;
20 }
21
22 bool line_law(point &st, point &ed, int n)
23 {
24 double line_k, line_b;
25 line_k = (ed.y - st.y)/(ed.x - st.x);
26 line_b = ed.y - line_k*ed.x;
27 double x = pipe[0][0].x;
28 double y = line_k*x + line_b;
29 if (y < pipe[0][0].y + EPS && pipe[0][1].y - EPS <= y)return true;
30 return false;
31 }
32
33 bool check(point &st, point &ed, double &MAX, int n)
34 {
35 double line_k, line_b;
36 line_k = (ed.y - st.y)/(ed.x - st.x);
37 line_b = ed.y - line_k*ed.x;
38 int flag;
39 if (!line_law(st,ed,n))return false;
40 double MIN = 1000000;
41 for (int i(0); i<n; ++i) {
42 double x = pipe[i][0].x;
43 double y = line_k*x + line_b;
44 if (y < pipe[i][0].y + EPS && y >= pipe[i][1].y - EPS)continue;
45 double seg_k, seg_b;
46 seg_k = (pipe[i][0].y - pipe[i-1][0].y)/(pipe[i][0].x - pipe[i-1][0].x);
47 seg_b = pipe[i][0].y - pipe[i][0].x*seg_k;
48 if (y < pipe[i][1].y - EPS) {
49 seg_k = (pipe[i][1].y - pipe[i-1][1].y)/(pipe[i][1].x - pipe[i-1][1].x);
50 seg_b = pipe[i][1].y - pipe[i][1].x*seg_k;
51 }
52 MIN = (line_b - seg_b)/(seg_k - line_k);
53 if (MIN != 1000000)break;
54 }
55 if (MIN != 1000000) {
56 MAX = MAX > MIN ? MAX:MIN;
57 return false;
58 } else {
59 return true;
60 }
61 }
62
63 int main()
64 {
65 int t;
66 while (scanf("%d",&t) && t) {
67 double len = -1000000;
68 for (int i(0); i<t; ++i) {
69 scanf("%lf%lf",&pipe[i][0].x,&pipe[i][0].y);
70 pipe[i][1].x = pipe[i][0].x;
71 pipe[i][1].y = pipe[i][0].y - 1;
72 }
73 bool flag = false;
74 for (int i(0); i<t; ++i) {
75 for (int k(0); k<2; ++k) {
76 for (int j(0); j<t; ++j) {
77 for (int l(0); l<2; ++l) {
78 if (i != j) {
79 if (check(pipe[i][k],pipe[j][l],len,t)) {
80 flag = true;
81 }
82 }
83 if (flag)break;
84 }
85 if (flag)break;
86 }
87 if (flag)break;
88 }
89 if (flag)break;
90 }
91 if (flag) {
92 cout<<"Through all the pipe."<<endl;
93 } else {
94 printf("%.2lf\n",len);
95 }
96 }
97 return 0;
98 }