标签:
poj1039:题目链接
题目大意:一条管子有n个折点,给出管子上壁n个点的坐标(x1,y1)(x2,y2)....,x1<x2<x3.....,其中管子粗是1,也就是说横截面的上面坐标(x,y),下面坐标(x,y-1)。问一束光从开始的点打入,最远照射到的位置,输出位置,或是全程
如果想让光照的最远,那么除了全程的可能外,光一定会与某一个管壁相交,并且会与管中的两个节点相交,否则就可以调整光的角度,使其照的更远,枚举这两个点的位置,然后逐个点处判断相交的位置。
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std ; #define eqs 1e-9 /* 两直线相交,求焦点 ax + by + c = 0 ; ux + vy + w = 0 ; a/u != b/v 防止平行 交点:( (b*w-v*c)/(a*v-u*b) , (c*u-a*w)/(a*v-u*b) ) */ struct point { double x , y ; } p[30]; int n ; double a[4][4] = { {0,0,0,0},{0,-1,0,0},{0,0,0,-1},{0,-1,0,-1} } ; double solve(point u,point v) { double a = (u.y-v.y)/(u.x-v.x) , b = u.y-a*u.x ; double x , y , ans = 0.0 ; int flag = 0 , i ; y = a*p[0].x + b ; if( y-p[0].y >= eqs || p[0].y-1.0-y >= eqs ) return ans ; for(i = 1 ; i < n ; i++) { y = a*p[i].x + b ; if( y-p[i].y > eqs ) { flag = 1 ; break ; } else if( p[i].y-1.0-y > eqs ) { flag = 2 ; break ; } else ans += (p[i].x-p[i-1].x) ; } if( !flag ) return ans ; u = p[i-1] , v = p[i] ; if( flag == 2 ) u.y -= 1.0 , v.y -= 1.0 ; double k = (u.y-v.y)/(u.x-v.x) , c = u.y-k*u.x ; x = (b-c)/(k-a) ; ans += (x-p[i-1].x) ; return ans ; } int main() { int i , j , k ; double max1 , temp ; point u , v ; while( scanf("%d", &n) && n ) { max1 = 0.0 ; for(i = 0 ; i < n ; i++) scanf("%lf %lf", &p[i].x, &p[i].y) ; for(i = 0 ; i < n ; i++) for(j = i+1 ; j < n ; j++) for(k = 0 ; k < 4 ; k++) { u.x = p[i].x + a[k][0] ; u.y = p[i].y + a[k][1] ; v.x = p[j].x + a[k][2] ; v.y = p[j].y + a[k][3] ; temp = solve(u,v) ; if( temp > max1 ) max1 = temp ; } if( fabs(p[n-1].x-p[0].x-max1) < eqs ) printf("Through all the pipe.\n") ; else printf("%.2lf\n", p[0].x+max1) ; } return 0 ; }
标签:
原文地址:http://blog.csdn.net/winddreams/article/details/45725845