题意:

无反射不透明管子, 问从入口射入的所有光线最远能到达的横坐标. 贯穿也可.

思路:

枚举每一组经过 up [ i ] 和 down [ j ] 的直线, 计算最远点.

因为无法按照光线生成的方式确定点斜式的起始点及斜率(连续的), 于是换另一种思路:

反正最终是要判断可行的直线, 就直接选择一些有代表性的直线, 覆盖所有边界即可.

于是考虑边界是什么.

首先可以发现: 由于光线是入口整个发出的, 其实也就是入口和拐点是平等的. 只要判相交.

只要覆盖在整个管道范围内的直线就可以, 由于不知道管道的形状特点, 只能暴力枚举每一组上下界. 能够完全穿过的直线就取"恰好与出口的一端相交"的情况.

这样做就将当前所枚举的两端点视为一段管道, 当前直线可以穿过当前等效管道, 判别是否可以穿过其他管道(包括等效管道内部的真实管道).

也就是将一系列判别满足的问题拆分为, 保证单个问题满足, 并用此一单个问题 粗略划定的范围去测试其它. 这样就解决了用来测试的范围无从确定的障碍.

难点就在于想到如何遍历所有可行的直线.

  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的顺侧还是逆侧*/
  42.  
  43. double cross(point A,point B,point P)//AB x AP
  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. }
  54.  
  55. /*计算直线AB和线段CD的交点横坐标*/
  56.  
  57. double intersection(point A,point B,point C,point D)
  58. {
  59. double area1=cross(A,B,C);
  60. double area2=cross(A,B,D);
  61. int c=dblcmp(area1);
  62. int d=dblcmp(area2);
  63.  
  64. if(c*d<0) //C,D在直线AB的两侧,规范相交
  65. return (area2*C.x - area1*D.x)/(area2-area1); //交点计算公式
  66.  
  67. if(c*d==0){ //CD的其中一个端点在AB上,不规范相交
  68. if(c==0)
  69. return C.x;
  70. else
  71. return D.x;
  72. }
  73. return -inf; //CD在AB同侧,无交点,返回 负无穷
  74. }
  75.  
  76. int main()
  77. {
  78. int n,i,j,k; //折点数
  79. while(cin>>n)
  80. {
  81. if(!n)
  82. break;
  83.  
  84. point* up=new point[n+1]; //上折点
  85. point* down=new point[n+1]; //下折点
  86.  
  87. double max_x=-inf; //最大可见度(管中最远可见点的横坐标)
  88. /*Input*/
  89.  
  90. for(i=1;i<=n;i++)
  91. {
  92. cin>>up[i].x>>up[i].y;
  93. down[i].x=up[i].x;
  94. down[i].y=up[i].y-1;
  95. }
  96.  
  97. bool flag=false; //标记当前光线L(直线up[i]->down[j])能否贯通全管
  98. for(i=1;i<=n;i++) //枚举所有通过一个上折点、一个下折点的直线
  99. {
  100. for(j=n;j>=1;j--)
  101. if(i!=j)
  102. {
  103. for(k=1;k<=n;k++) //直线L最大延伸到第k-1节管子
  104. if(!check(up[i],down[j],up[k],down[k])) //up[k]->down[k]为折点处垂直x轴的直线
  105. break;
  106.  
  107. if(k>n)//顺利结束循环,可以贯穿
  108. {
  109. flag=true;
  110. break;
  111. }
  112. else if(k>max(i,j)) //判断与第k-1节管子的上管壁还是下管壁相交
  113. {
  114. double temp=intersection(up[i],down[j],up[k],up[k-1]);
  115. if(max_x < temp)
  116. max_x=temp;
  117.  
  118. temp=intersection(up[i],down[j],down[k],down[k-1]);
  119. if(max_x < temp)
  120. max_x=temp;
  121. }
  122. }
  123.  
  124. if(flag)
  125. break;
  126. }
  127.  
  128. if(flag)
  129. cout<<"Through all the pipe."<<endl;
  130. else
  131. cout<<fixed<<setprecision(2)<<max_x<<endl;
  132.  
  133. /*Relax Room*/
  134.  
  135. delete up;
  136. delete down;
  137. }
  138. return 0;
  139. }

自己敲一遍:

  1. #include <cstdio>
  2. #include <cmath>
  3. using namespace std;
  4. const double EPS = 1e-6;///写成int了= =
  5. const int INF = 0x3f3f3f3f;
  6. const int MAXN = 25;
  7. typedef struct node
  8. {
  9. double x,y;
  10. }point;
  11. point up[MAXN],down[MAXN];
  12.  
  13. int max(int a, int b)
  14. {
  15. int diff = b - a;
  16. return b - (diff & (diff>>31));
  17. }
  18.  
  19. int dcmp(double p)
  20. {
  21. if(fabs(p)<EPS)
  22. return 0;
  23. return p>0?1:-1;
  24. }
  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 P)
  32. {
  33.  
  34. return det(B.x - A.x, B.y - A.y, P.x - A.x, P.y - A.y);;
  35. }
  36.  
  37. bool check(point A, point B, point C, point D)
  38. {
  39. return (dcmp(cross(A, B, C)) * dcmp(cross(A, B, D)) <= 0);//规范或不规范相交
  40. }
  41.  
  42. double intersection(point A, point B, point C, point D)
  43. {
  44. double area1 = cross(A, B, C);
  45. double area2 = cross(A, B, D);
  46. int c = dcmp(area1);
  47. int d = dcmp(area2);
  48. if(c*d<0)
  49. {
  50. return (area2 * C.x - area1 * D.x)/(area2 - area1);
  51. }
  52. if(!(c*d))
  53. {
  54. if(!c)
  55. return C.x;
  56. else
  57. return D.x;
  58. }
  59. return -INF;
  60. }
  61.  
  62. int main()
  63. {
  64. int n;
  65. while(scanf("%d",&n)==1 && n)
  66. {
  67. double Mx = -INF;
  68. for(int i=1;i<=n;i++)
  69. {
  70. scanf("%lf %lf",&up[i].x,&up[i].y);
  71. down[i].x = up[i].x,down[i].y = up[i].y - 1;
  72. }
  73. bool flag = false;
  74. for(int i=1;i<=n;i++)
  75. {
  76. for(int j=1,k;j<=n;j++)
  77. {
  78. if(i==j)
  79. continue;
  80. for(k=1;k<=n;k++)
  81. {
  82. if(!check(up[i],down[j],up[k],down[k]))
  83. break;
  84. }
  85.  
  86. if(k>n)
  87. {
  88. flag = true;
  89. break;
  90. }
  91. if(k>max(i,j))
  92. {
  93. double temp = intersection(up[i],down[j],up[k],up[k-1]);
  94. if(Mx < temp)
  95. Mx = temp;
  96. temp = intersection(up[i],down[j],down[k],down[k-1]);
  97. if(Mx < temp)
  98. Mx = temp;
  99. }
  100. }
  101. if(flag)
  102. break;
  103. }
  104. if(flag)
  105. printf("Through all the pipe.\n");
  106. else
  107. printf("%.2lf\n",Mx);
  108. }
  109.  
  110. }

[poj 1039]Pipes[线段相交求交点]的更多相关文章

  1. POJ 1039 Pipe | 线段相交

    题目: 给一个管子,有很多转弯处,问从管口的射线射进去最长能射到多远 题解: 根据黑书,可以证明的是这条光线一定经过了一个上顶点和下顶点 所以我们枚举每对上下顶点就可以了 #include<cs ...

  2. poj 1066(枚举+线段相交)

    Treasure Hunt Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6328   Accepted: 2627 Des ...

  3. fzu 1015 土地划分(判断线段相交+求出交点+找规律)

    链接:http://acm.fzu.edu.cn/problem.php?pid=1015  Problem 1015 土地划分 Accept: 714    Submit: 1675Time Lim ...

  4. [poj] 2074 Line of Sight || 直线相交求交点

    原题 给出一个房子(线段)的端点坐标,和一条路的两端坐标,给出一些障碍物(线段)的两端坐标.问在路上能看到完整房子的最大连续长度是多长. 将障碍物按左端点坐标排序,然后用房子的右端与障碍物的左端连线, ...

  5. C - Segments POJ - 3304 (判断线段相交)

    题目链接:https://vjudge.net/contest/276358#problem/C 题目大意:给你n条线段,问你是否存在一条线段使得所有的线段在这条直线的投影至少具有一个交点? 具体思路 ...

  6. HDU 1828 / POJ 1177 Picture --线段树求矩形周长并

    题意:给n个矩形,求矩形周长并 解法:跟求矩形面积并差不多,不过线段树节点记录的为: len: 此区间线段长度 cover: 此区间是否被整个覆盖 lmark,rmark: 此区间左右端点是否被覆盖 ...

  7. poj 1410 Intersection 线段相交

    题目链接 题意 判断线段和矩形是否有交点(矩形的范围是四条边及内部). 思路 判断线段和矩形的四条边有无交点 && 线段是否在矩形内. 注意第二个条件. Code #include & ...

  8. Rikka with Mista 线段树求交点个数

    由于上下线段是不可能有交点的 可以先看左右线段树,按照y递增的顺序,对点进行排序. 升序构造,那么对于从某一点往下的射线,对于L,R进行区间覆盖,线段交点个数就是单点的被覆盖的次数. 降序构造,那么对 ...

  9. POJ 1151 Atlantis 线段树求矩形面积并 方法详解

    第一次做线段树扫描法的题,网搜各种讲解,发现大多数都讲得太过简洁,不是太容易理解.所以自己打算写一个详细的.看完必会o(∩_∩)o 顾名思义,扫描法就是用一根想象中的线扫过所有矩形,在写代码的过程中, ...

随机推荐

  1. elasticsearh 中每个节点中需要有相同的插件

    elasticsearh 中每个节点中需要有相同的插件 [2016-09-13 19:25:24,049][INFO ][discovery.zen ] [node02] failed to send ...

  2. Sum Root to Leaf Numbers 解答

    Question Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent ...

  3. VMdomainXml

    1,One,Euc,Ostack 虚拟磁盘镜像制作方法[Windows,Linux,类linux OS](1,基于ios部署系统生成img,2基于vm xml定义部署系统生成img qcow2) 如需 ...

  4. cookielib模块基础学习

    # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' import cookielib #主要用于处理http客户端的co ...

  5. 黑马程序猿 IO流 ByteArrayInputStream与ByteArrayOutputStream

    ---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ---------------------- package cn.itcast.IO; i ...

  6. 成语接龙(dfs)

    成语接龙 Time Limit: 1000 MS Memory Limit: 32768 K Total Submit: 92(17 users) Total Accepted: 23(14 user ...

  7. Oracle-nomount/mount/open

    通常所说的Oracle Server主要由两个部分组成:Instance和Database.Instance是指一组后台进程(在Windows上是一组线程)和一块共享内存区域:Database是指存储 ...

  8. SQLLoader8(加载的数据中有换行符处理方法)

    SQLLDR加载的数据中有换行符处理方法1.创建测试表: CREATE TABLE MANAGER( MGRNO NUMBER, MNAME ), JOB ), REMARK ) ); 2.创建控制文 ...

  9. simplify the life ECMAScript 5(ES5)中bind方法简介

    一直以来对和this有关的东西模糊不清,譬如call.apply等等.这次看到一个和bind有关的笔试题,故记此文以备忘. bind和call以及apply一样,都是可以改变上下文的this指向的.不 ...

  10. json返回数据拼接HTML

    <div class="box-lists">  </div> $.ajax({ url: 'AjaxPage/AjaxHandler.ashx', typ ...