zoukankan      html  css  js  c++  java
  • POJ1039Pipe

    转载请注明出处:優YoU http://user.qzone.qq.com/289065406/blog/1302329342

    大致题意:

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

     

    解题思路:

    刘汝佳《算法艺术与信息学艺术》第三章 计算几何初步 的例2  P359

    (别人叫它黑书,小菜们看不懂什么意思,我稍微解释了,确实这书表面内里一般黑。。。)

    一模一样的题

    把那本书3.1节读透了,就能理解这题了,但理解不一定会做


     

    我第一次做计算几何的题,不看着模板根本做不下去= = 惭愧。。。。纠结多天了,现在还对模板计算的交点算法存在一个疑问。。。迟点请教大牛,现在先贴题

     

    要点难点我都注释在我的程序里了,程序模块分得很多,看着就习惯了

     

      1 //Memory  Time 
    2 //456K 63MS
    3
    4 #include<iostream>
    5 #include<cmath>
    6 #include<iomanip>
    7 using namespace std;
    8
    9 const double precision=1e-3; //精度限制
    10 const double inf=99999.0; //正无穷,注意下面使用的是负无穷
    11
    12 typedef class Node //折点坐标
    13 {
    14 public:
    15 double x;
    16 double y;
    17 }point;
    18
    19 int max(int a,int b)
    20 {
    21 return a>b?a:b;
    22 }
    23
    24 /*把浮点p的值转化为0,1或-1 (精度讨论)*/
    25
    26 int dblcmp(double p)
    27 {
    28 if(fabs(p)<precision) // fabs() 浮点数的绝对值
    29 return 0; //只要是在0的邻域,就认为是0
    30
    31 return p>0?1:-1;
    32 }
    33
    34 /*叉积运算*/
    35
    36 double det(double x1,double y1,double x2,double y2)
    37 {
    38 return x1*y2-x2*y1;
    39 }
    40
    41 /*计算P点在AB的左侧还是右侧(AC与AB的螺旋关系)*/
    42
    43 double cross(point A,point B,point P)
    44 {
    45 return det(B.x-A.x , B.y-A.y , P.x-A.x , P.y-A.y);
    46 }
    47
    48 /*判断直线AB、CD是否相交*/
    49
    50 bool check(point A,point B,point C,point D)
    51 {
    52 return (dblcmp(cross(A,B,C)) * dblcmp(cross(A,B,D)) <= 0);
    53 //这里对黑书P353所述模板的相交约束条件做了修改
    54 //目的是允许 入射光线L 与 折点处垂线 不规范相交(即垂线的端点可以落在L上 或者 允许延长线相交)
    55 }
    56
    57 /*计算直线AB、CD的交点横坐标*/
    58 //本题这里传参是有讲究的,AB是代表光线L与管道的交点,CD是代表上管壁或者下管壁的端点
    59 //之所以这样做,是因为AB与CD实质上是不相交的,是AB的延长线与CD相交
    60 //按照上述传参顺序,根据修改后的模板,那么仅仅判断C、D是否在AB的两侧,就能计算 AB延长线与CD的交点
    61 //倘若传参顺序错了,就会判断A、B是否在CD的两侧,但是AB一定是在CD同侧的,也就不能求交点了
    62
    63 double intersection(point A,point B,point C,point D)
    64 {
    65 double area1=cross(A,B,C);
    66 double area2=cross(A,B,D);
    67 int c=dblcmp(area1);
    68 int d=dblcmp(area2);
    69
    70 if(c*d<0) //CD在AB的两侧,规范相交
    71 return (area2*C.x - area1*D.x)/(area2-area1); //黑书P357交点计算公式
    72
    73 if(c*d==0) //CD的其中一个端点在AB上,不规范相交
    74 if(c==0)
    75 return C.x;//C在AB上,返回AB与CD非规范相交时的交点C的横坐标
    76 else
    77 return D.x;//D在AB上,返回AB与CD非规范相交时的交点D的横坐标
    78
    79 return -inf; //CD在AB同侧,无交点,返回 负无穷
    80 }
    81
    82 int main(int i,int j,int k)
    83 {
    84 int n; //折点数
    85 while(cin>>n)
    86 {
    87 if(!n)
    88 break;
    89
    90 point* up=new point[n+1]; //上折点
    91 point* down=new point[n+1]; //下折点
    92
    93 double max_x=-inf; //最大可见度(管中最远可见点的横坐标)
    94 /*Input*/
    95
    96 for(i=1;i<=n;i++)
    97 {
    98 cin>>up[i].x>>up[i].y;
    99 down[i].x=up[i].x;
    100 down[i].y=up[i].y-1;
    101 }
    102
    103 bool flag=false; //标记当前光线L(直线up[i]->down[j])能否贯通全管
    104 for(i=1;i<=n;i++) //枚举所有通过一个上折点、一个下折点的直线
    105 {
    106 for(j=1;j<=n;j++)
    107 if(i!=j)
    108 {
    109 for(k=1;k<=n;k++) //直线L最大延伸到第k-1节管子
    110 if(!check(up[i],down[j],up[k],down[k])) //up[k]->down[k]为折点处垂直x轴的直线
    111 break;
    112
    113 if(k>n)
    114 {
    115 flag=true;
    116 break;
    117 }
    118 else if(k>max(i,j)) //由于不清楚L究竟是与第k-1节管子的上管壁还是下管壁相交,因此都计算交点,取最优
    119 { //举例:若实际L是与上管壁相交,当计算下管壁时,得到的是第k-1个下折点,并不会是最优
    120 //反之亦同理
    121 double temp=intersection(up[i],down[j],up[k],up[k-1]);
    122 if(max_x < temp) //L与第k-1节管子的上管壁相交
    123 max_x=temp;
    124
    125 temp=intersection(up[i],down[j],down[k],down[k-1]);
    126 if(max_x < temp) //L与第k-1节管子的上管壁相交
    127 max_x=temp;
    128 }
    129 }
    130
    131 if(flag)
    132 break;
    133 }
    134
    135 if(flag)
    136 cout<<"Through all the pipe."<<endl;
    137 else
    138 cout<<fixed<<setprecision(2)<<max_x<<endl;
    139
    140 /*Relax Room*/
    141
    142 delete up,down;
    143 }
    144 return 0;
    145 }

     

  • 相关阅读:
    【ASP.NET】服务器控件大演练与实例分析
    【利用存储过程和三层架构完成新闻发布】
    【软件工程】web规格开发全过程
    【数据库】如何解决数据库附加失败问题
    【框架设计】异常
    【数据库】SqlCommand的几个易忽视的执行操作
    【ASP.NET】asp.net 页面调用服务端对象值
    【c#迭代器】
    【框架设计】CLR寄宿和应用程序域
    【ASP.NET】演绎GridView基本操作事件
  • 原文地址:https://www.cnblogs.com/lyy289065406/p/2122818.html
Copyright © 2011-2022 走看看