• poj 1039 Pipe (计算几何)


    题目:http://poj.org/problem?id=1039

    刘汝佳的黑书《算法艺术与信息学竞赛》上的第3章计算几何初步的例2  管道问题

    有一宽度为1的折线管道,上面顶点为(xi,yi),所对应的下面顶点为(xi,yi-1),假设管道都是不透明的,不反射的,光线从左边入口处的(x1,y1),(x1,y1-1)之间射入,向四面八方传播,求解光线最远能传播到哪里(取x坐标)或者是否能穿透整个管道.

    思路:首先,一根光纤自始至终未曾擦到任何顶点,肯定不是最优的(可以平移使之优化),然后,如果只碰到一个顶点,那也不是最优的,可以通过旋转,是他碰到另一个顶点,并且更优,最后要说明,最优光线必然是擦到一个上顶点,一个下顶点。。。。

    任取一个上顶点一个下顶点形成直线L,然后从左到右依次判断管壁与其相不相交,若相交停止循环找出交点与之前的交点比较,找到最大的x即可,若一直都不想交则就是L射穿了整个管道。。。

    代码:

     

    View Code
      1 #include <iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 using namespace std;
      5 typedef struct node
      6 {
      7     double x,y;
      8 }point;
      9 point up[31];
     10 point down[31];
     11 const double eps=1e-8;
     12 const double inf=99999.0;
     13 int max(int a,int b)
     14 {
     15     if(a>b)
     16     return a;
     17     else
     18     return b;
     19 }
     20 int dblcmp(double d)//浮点误差的处理
     21 {
     22     if(fabs(d)<eps)
     23     return 0;
     24     return (d>0)?1:-1;
     25 }
     26 double det (double x1,double y1,double x2,double y2)//叉乘
     27 {
     28     return x1*y2-x2*y1;
     29 }
     30 
     31 double cross(point a,point b,point c)
     32 {
     33     return det(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);//向量
     34 }
     35 
     36 int pan(point a,point b,point c,point d)
     37 {
     38     return (dblcmp(cross(a,b,c))*dblcmp(cross(a,b,d))<=0);//规范相交和与顶点相交的两种不规范相交
     39 }
     40 
     41 double get_x(point a,point b,point c,point d)//求交点
     42 {
     43     double area1=cross(a,b,c);
     44     double area2=cross(a,b,d);
     45     int d1=dblcmp(area1);
     46     int d2=dblcmp(area2);
     47     if(d1*d2<0)
     48     return (area2*c.x-area1*d.x)/(area2-area1);//规范相交的交点公式
     49     if(d1*d2==0)
     50     {
     51         if(d1==0)//交于第k-1个点
     52         return c.x;
     53         else//交于第k个点
     54         return d.x;
     55     }
     56     return -inf;//不相交
     57 }
     58 int main()
     59 {
     60     int n;
     61     while(scanf("%d",&n)!=EOF)
     62     {
     63         if(n==0)
     64         break;
     65         int i,j;
     66         for(i=0;i<n;i++)
     67         {
     68             scanf("%lf%lf",&up[i].x,&up[i].y);
     69             down[i].x=up[i].x;
     70             down[i].y=up[i].y-1;
     71         }
     72         //依次枚举每个点
     73         int flag=0;
     74         double res=-inf;//初始化为最小负数,因为坐标可能为负的
     75         int k;
     76         for(i=0;i<n;i++)
     77         {
     78             for(j=0;j<n;j++)
     79             {
     80                 if(i==j)
     81                 continue;
     82                 for(k=0;k<n;k++)
     83                 {
     84                     if(!pan(up[i],down[j],up[k],down[k]))//判断直线L能否穿过k点的管道
     85                     break;
     86                 }
     87                 if(k>=n)//穿过全部的管道
     88                 {
     89                     flag=1;
     90                     break;
     91                 }
     92                 else
     93                 {
     94                     if(k>max(i,j))
     95                     {
     96                         double uu=get_x(up[i],down[j],up[k-1],up[k]);//与上管壁相交的情况
     97                         if(res<uu)
     98                         res=uu;
     99                         uu=get_x(up[i],down[j],down[k-1],down[k]);//与下管壁相交的情况
    100                         if(res<uu)
    101                         res=uu;
    102                     }
    103 
    104                 }
    105             }
    106             if(flag)
    107             break;
    108         }
    109         if(flag==1)
    110         printf("Through all the pipe.\n");
    111         else
    112         printf("%.2f\n",res);
    113     }
    114     return 0;
    115 }
  • 相关阅读:
    观察者模式
    Java中关于HashMap源码的研究
    抽象工厂模式
    适配器模式
    oracle创建表空间并赋予权限
    外观模式
    oracle中循环读出一个表的信息插入到另外一个表中
    javaScript对金额处理的方式
    装饰器模式
    建造者模式
  • 原文地址:https://www.cnblogs.com/wanglin2011/p/2932299.html
Copyright © 2020-2023  润新知