poj1039Pipe(直线交点、叉积)
之前刷poj计划时刷过,不过也没什么印象了。打铁还是趁热,还没热起来就放弃了,前面算是做了无用功,有如胡乱的看解题报告一样。
题目应该是比较经典的集合入门题,黑书上有一部分核心讲解。
题目中的最优光线必是要经过端点,这个黑书上提到了,应该也可以想到,然后就可以枚举一上一下的端点,判断它最长能走到哪里,首先可以判断出它是否能进的去第i个入口,
这个可以通过叉积进行判断上下点是不是在这条光线异侧,然后求直线的交点。
有一份好的模板很重要~
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 55 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 struct Point 18 { 19 double x,y; 20 Point(double x=0,double y=0):x(x),y(y) {} //构造函数 方便代码编写 21 }p[N]; 22 typedef Point pointt; 23 pointt operator + (Point a,Point b) 24 { 25 return Point(a.x+b.x,a.y+b.y); 26 } 27 pointt operator - (Point a,Point b) 28 { 29 return Point(a.x-b.x,a.y-b.y); 30 } 31 pointt operator * (Point a,double b) 32 { 33 return Point(a.x*b,a.y*b); 34 } 35 pointt operator / (Point a,double b) 36 { 37 return Point(a.x/b,a.y/b); 38 } 39 bool operator < (const Point &a,const Point &b) 40 { 41 return a.x<b.x||(a.x==b.x&&a.y<b.y); 42 } 43 int dcmp(double x) 44 { 45 if(fabs(x)<eps) return 0; 46 else return x<0?-1:1; 47 } 48 bool operator == (const Point &a,const Point &b) 49 { 50 return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0; 51 } 52 //求点积以及利用点积求长度和夹角的函数 53 double dot(Point a,Point b) 54 { 55 return a.x*b.x+a.y*b.y; 56 } 57 double cross(Point a,Point b,Point c)//差乘判左右 a->b与a->c向量的关系 58 { 59 return (a.x-c.x)*(a.y-b.y)-(a.y-c.y)*(a.x-b.x); 60 } 61 bool intersection1(Point p1, Point p2, Point p3, Point p4, Point& p) // 直线相交 62 { 63 double a1, b1, c1, a2, b2, c2, d; 64 a1 = p1.y - p2.y; 65 b1 = p2.x - p1.x; 66 c1 = p1.x*p2.y - p2.x*p1.y; 67 a2 = p3.y - p4.y; 68 b2 = p4.x - p3.x; 69 c2 = p3.x*p4.y - p4.x*p3.y; 70 d = a1*b2 - a2*b1; 71 if (!dcmp(d)) return false; 72 p.x = (-c1*b2 + c2*b1) / d; 73 p.y = (-a1*c2 + a2*c1) / d; 74 return true; 75 } 76 int main() 77 { 78 int n,i,j,g; 79 while(scanf("%d",&n)&&n) 80 { 81 for(i = 1; i <= n ; i++) 82 { 83 scanf("%lf%lf",&p[i].x,&p[i].y); 84 p[i+n].x = p[i].x; 85 p[i+n].y = p[i].y-1.0; 86 } 87 double ans = -INF; 88 int flag = 0; 89 for(i = 1 ; i <= n; i++) 90 { 91 for(j = n+1 ; j <= 2*n ; j++) 92 { 93 if(j==n+i) continue; 94 Point sg ; 95 for(g = 1; g <= n ; g++) 96 { 97 int d1 = dcmp(cross(p[i],p[j],p[g])); 98 int d2 = dcmp(cross(p[i],p[j],p[g+n])); 99 if(g==1&&d1*d2<=0) continue; 100 if(g==1&&d1*d2>0) break; 101 if(d1*d2>0) 102 { 103 if(intersection1(p[i],p[j],p[g-1],p[g],sg)) 104 { 105 ans = max(ans,sg.x); 106 } 107 if(intersection1(p[i],p[j],p[n+g-1],p[n+g],sg)) 108 { 109 ans = max(ans,sg.x); 110 } 111 break; 112 } 113 } 114 if(g>n) 115 { 116 flag = 1; 117 break; 118 } 119 } 120 if(flag) break; 121 } 122 if(flag) puts("Through all the pipe."); 123 else printf("%.2f\n",ans); 124 } 125 return 0; 126 }