题干:

You are to find the length of the shortest path through a chamber containing obstructing walls. The chamber will always have sides at x = 0, x = 10, y = 0, and y = 10. The initial and final points of the path are always (0, 5) and (10, 5). There will also be from 0 to 18 vertical walls inside the chamber, each with two doorways. The figure below illustrates such a chamber and also shows the path of minimal length.

Input

The input data for the illustrated chamber would appear as follows.


4 2 7 8 9 
7 3 4.5 6 7

The first line contains the number of interior walls. Then there is a line for each such wall, containing five real numbers. The first number is the x coordinate of the wall (0 < x < 10), and the remaining four are the y coordinates of the ends of the doorways in that wall. The x coordinates of the walls are in increasing order, and within each line the y coordinates are in increasing order. The input file will contain at least one such set of data. The end of the data comes when the number of walls is -1.

Output

The output should contain one line of output for each chamber. The line should contain the minimal path length rounded to two decimal places past the decimal point, and always showing the two decimal places past the decimal point. The line should contain no blanks.

Sample Input

1
5 4 6 7 8
2
4 2 7 8 9
7 3 4.5 6 7
-1

Sample Output

10.00
10.06

题目大意:

房间里有n堵墙,每面墙上有两扇门,求从房间最左端中点到最右端中点的最短路径

解题报告:

把起点,终点,每个墙上的4个点分别看成图的顶点,这样一共就是4*n+2个点,我们把起点和终点当做第4*n+1和4*n+2这两个点,其余的每四个点为一组读数,读完顺便加边。

然后就是把这个点和之前所有读过的点连成一条边(假设共能连cnt条边),然后每条边依次连好的边(也就是墙)判断是否相交,如果和所有的墙都不相交,那么就加边(到dis数组中),然后跑floyd最短路就可以了。

写代码能力还是挫啊、、搞了一小时、、

AC代码:

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstdio>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const double eps = 1e-8;
int sgn(double x) {if(fabs(x) < eps)return 0;if(x < 0) return -1;return 1;
}
struct Point {double x,y;Point() {}Point(double x,double y):x(x),y(y) {}Point operator -(const Point &b)const {return Point(x - b.x,y - b.y);}double operator ^(const Point &b)const {return x*b.y - y*b.x;}double operator *(const Point &b)const {return x*b.x + y*b.y;}
} p[1005];
struct Line {Point s,e;Line() {}Line(Point s,Point e):s(s),e(e) {}pair<Point,int> operator &(const Line &b)const {Point res = s;if(sgn((s-e)^(b.s-b.e)) == 0) {if(sgn((b.s-s)^(b.e-s)) == 0)return make_pair(res,0);//两直线重合else return make_pair(res,1);//两直线平行}double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));res.x += (e.x - s.x)*t;res.y += (e.y - s.y)*t;return make_pair(res,2);//有交点,并返回交点}
} line[1005];
inline double xmult(Point p0,Point p1,Point p2) { return (p1-p0)^(p2-p0);}//p0p1 X p0p2
bool Seg_inter_line(Line l1,Line l2) { return sgn(xmult(l2.s,l1.s,l1.e))*sgn(xmult(l2.e,l1.s,l1.e)) <= 0;}//判断直线l1和线段l2是否相交
double dist(Point a,Point b) {return sqrt((b - a)*(b - a));}
bool inter(Line l1,Line l2) {//判断线段相交returnmax(l1.s.x,l1.e.x)>=min(l2.s.x,l2.e.x)&&max(l2.s.x,l2.e.x)>=min(l1.s.x,l1.e.x)&&max(l1.s.y,l1.e.y)>=min(l2.s.y,l2.e.y)&&max(l2.s.y,l2.e.y)>=min(l1.s.y,l1.e.y)&&sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s))<=0&&sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s))<=0;
}
//两线段相交判断
//2 规范相交
//1 非规范相交
//0 不相交
int segcrossseg(Line l1,Line l2) {int d1 = sgn((l1.e-l1.s)^(l2.s-l1.s));int d2 = sgn((l1.e-l1.s)^(l2.e-l1.s));int d3 = sgn((l2.e-l2.s)^(l1.s-l2.s));int d4 = sgn((l2.e-l2.s)^(l1.e-l2.s));if( (d1^d2)==-2 && (d3^d4)==-2 )return 2;return (d1==0 && sgn((l2.s-l1.s)*(l2.s-l1.e))<=0) ||(d2==0 && sgn((l2.e-l1.s)*(l2.e-l1.e))<=0) ||(d3==0 && sgn((l1.s-l2.s)*(l1.s-l2.e))<=0) ||(d4==0 && sgn((l1.e-l2.s)*(l1.e-l2.e))<=0);
}
//直线和线段相交判断
//-*this line -v seg
//2 规范相交
//1 非规范相交
//0 不相交
int linecrossseg(Line l1,Line l2) {//l1直线,l2线段 int d1 = sgn((l1.e-l1.s)^(l2.s-l1.s));int d2 = sgn((l1.e-l1.s)^(l2.e-l1.s));if((d1^d2)==-2) return 2;return (d1==0||d2==0);
}
int totP,totL;
int n;
double dis[1005][1005];
void add(int num) {int up = num%4==0 ?  num-4 : num-(num%4);//最多跑到哪个点 for(int i = 1; i<=up; i++) {int flag = 1;for(int j = 1; j<=totL; j++) {if(segcrossseg(Line(p[num],p[i]),line[j]) == 2) {flag=0;break;}}if(flag) {dis[i][num] = dis[num][i] = dist(p[i],p[num]);}}//与起点 int flag = 1;for(int j = 1; j<=totL; j++) {if(segcrossseg(Line(p[num],p[4*n+1]),line[j]) == 2) {flag=0;break;}}if(flag) {dis[4*n+1][num] = dis[num][4*n+1] = dist(p[4*n+1],p[num]);}
}
int main()
{double y1,y2,y3,y4,x;while(~scanf("%d",&n)) {if(n == -1) break;//共4*n+1个顶点totP = 0;//因为起点 站了一个了 (还是起点单独算吧、、、) totL = 0;p[4*n+1] = Point(0,5);p[4*n+2] = Point(10,5);for(int i = 1; i<=4*n+10; i++) {for(int j = 1; j<=4*n+10; j++) {dis[i][j] = 1000000000;}}for(int i = 1; i<=n; i++) {scanf("%lf%lf%lf%lf%lf",&x,&y1,&y2,&y3,&y4);p[++totP] = Point(x,y1);line[++totL] = Line(Point(x,0),p[totP]);p[++totP] = Point(x,y2);p[++totP] = Point(x,y3);line[++totL] = Line(p[totP-1],p[totP]);p[++totP] = Point(x,y4);line[++totL] = Line(p[totP],Point(x,10));add(totP);add(totP-1);add(totP-2);add(totP-3);}add(4*n+2);
//      dis[totP][4*n+2] = dis[4*n+2][totP] = dist(Point(totP),Point(p[4*n+2]));
//      dis[totP-1][4*n+2] = dis[4*n+2][totP] = dist(Point(totP),Point(p[4*n+2]));
//      dis[totP][4*n+2] = dis[4*n+2][totP] = dist(Point(totP),Point(p[4*n+2]));
//      dis[totP][4*n+2] = dis[4*n+2][totP] = dist(Point(totP),Point(p[4*n+2]));for(int k = 1; k<=totP+2; k++) {for(int i = 1; i<=totP+2; i++) {for(int j = 1; j<=totP+2; j++) {if(dis[i][k] + dis[k][j] < dis[i][j]) {dis[i][j] = dis[i][k] + dis[k][j];}}}}printf("%.2f\n",dis[4*n+1][4*n+2]);}
}
/*
1
7 3 4.5 6 7*/ 

总结:

说一下选定思路后开始敲代码的历程,首先模板没的说,然后开始想读入点的时候,用构造函数构造点,构造边,是都需要记录下来呢还是可以只构造点,然后遍历的时候再   每两个点连成一条边    来进行判断,后来发现这样不太好,也不太适合。因为你这样会把  -每条墙的边和矩形的边框的边的交点-  那个点,也算在判断的范围中了,但是我们是不需要这个点的,也就是说不需要判断这个点和其他点之间的关系,所以我们考虑也把每一条可以用到的边都记录下来,然后一边读入一边存点存边并且构图(最短路的图),刚开始想把起点存成id=1,终点存成id=4*n+2,但是发现这样不太好,因为这样就打乱了四条边一组的这一不错的关系,因为用这一关系(因为可以取模了啊 毕竟可以分组),我们可以用一个处理就得出了我们需要判断的up的值,(如果不是这种存id的方法的话,那就是2,3,4,5是一组,6,7,8,9是一组,这样就得写一堆if else、、)然后写add函数,刚开始直接up=num-(num%4),后来发现第一个样例都跑不出来,找bug,找到,改。这也是一个小trick啊以后别再犯了、、、找到这个bug的同时发现我没有让他和起点去连线(因为他的坐标是4*n+1啊所以肯定没有被比较过)所以我们需要单独让他俩连线跑一次。

然后第二个样例没过去,检查后发现是最短路中应该是totP+2,我忘了+2了。。

然后 dis数组初始化,本来想memset,,一想不对啊这是double类型,不能memset了,,然后最后写了四行想让终点和最后一个墙中的点都建图,但是一想这样写不好,因为可能他和其他前面的墙也可以建图呢。。所以直接add一下得了。。于是乎代码出来了。。。然后一发AC、、

坑点

【POJ - 1556】The Doors (计算几何,线段相交)相关推荐

  1. poj 1556 (Dijkstra + Geometry 线段相交)

    链接:http://poj.org/problem?id=1556 The Doors Time Limit: 1000MS   Memory Limit: 10000K Total Submissi ...

  2. POJ 1556 The Doors(计算几何+最短路)

    这题就是,处理出没两个点.假设能够到达,就连一条边,推断可不能够到达,利用线段相交去推断就可以.最后求个最短路就可以 代码: #include <cstdio> #include < ...

  3. Poj 1556 The Doors 计算几何+最短路

    其实本题非常的无脑,无脑拍完1A,写到blog里只因为TM无脑拍也拍了很久啊= = #include <cstdio> #include <cstring> #include ...

  4. 简单几何(线段相交+最短路) POJ 1556 The Doors

    题目传送门 题意:从(0, 5)走到(10, 5),中间有一些门,走的路是直线,问最短的距离 分析:关键是建图,可以保存所有的点,两点连通的条件是线段和中间的线段都不相交,建立有向图,然后用Dijks ...

  5. POJ 2653 Pick-up sticks (线段相交)

    题意:给你n条线段依次放到二维平面上,问最后有哪些没与前面的线段相交,即它是顶上的线段 题解:数据弱,正向纯模拟可过 但是有一个陷阱:如果我们从后面向前枚举,找与前面哪些相交,再删除前面那些相交的线段 ...

  6. NYOJ 1016 德莱联盟(计算几何 线段相交判定)

    判断两条线段是否相交. 在判断两条线段是否相交时,我们常用快速排斥实验跟跨立实验这两种方法,快速排斥实验能很快的排除掉线段不相交的情况,但并没法成为线段相交的充要条件,在快速排斥实验之后接上跨立实验就 ...

  7. 德莱联盟 计算几何 线段相交

    难度:1 描述 欢迎来到德莱联盟.... 德莱文... 德莱文在逃跑,卡兹克在追.... 我们知道德莱文的起点和终点坐标,我们也知道卡兹克的起点和 终点坐标,问:卡兹克有可能和德莱文相遇吗?,并且保证 ...

  8. POJ 2653 Pick-up sticks 判断线段相交

    枚举每条线段 这条线段上面没有与它相交的线段 #include <iostream> #include <cstdio> #include <cstring> #i ...

  9. POJ 1556 The Doors (未完)

    -- 转载于:https://www.cnblogs.com/XDJjy/p/3209296.html

  10. zoj 1010 Area【线段相交问题】

    链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1010 http://acm.hust.edu.cn/vjudge/ ...

最新文章

  1. pandas DataFrame(5)-合并DataFrame与Series
  2. centos mysql压缩文件直接恢复_Centos下mysql数据库备份与恢复的方法
  3. Django 实现WEB登陆(第二版)
  4. 【深度学习】动漫风格迁移AnimeGANv2,发布线上运行Demo
  5. SpringAop对struts2的Action设置切面织入时报错java.lang.NoSuchMethodException
  6. Maven 搭建多模块企业级项目
  7. 对象作为函数参数可能会导致的问题
  8. CentOS 6.5 部署WordPress
  9. drools简单应用
  10. HDU5528 - Count a * b
  11. Python 连接MongoDB并比较两个字符串相似度的简单示例
  12. catia如何画花键_CATIA到底有多用呢~
  13. 好好学习 天天编程—C语言之我的第一个hello world(二)
  14. 学习docker on windows (1): 为什么要使用docker
  15. 应用多元统计分析第四章基于最小二乘估计线性回归分析python代码
  16. 人声歌姬语音合成器+全套拓展 – Yamaha Vocaloid 4.3.0 + ALL Libraries WiN
  17. CentOS 8 安装tc流量控制工具
  18. SpringBoot中怎么访问静态图片
  19. 【非广告】2021 入门级的 Java 程序员学习路线图 1.0
  20. python中列表(list)的基本定义和用法

热门文章

  1. [dp] LeetCode 91. Decode Ways
  2. ios 部分string颜色_iOS-代码混淆加固方案
  3. MySQL水表查询系统_水费管理系统
  4. 文件服务器上传文件的过程,文件服务器上传文件实现过程【分享】
  5. 外部仓库_仓库主要作业流程和WMS作业优化方案
  6. 快速理解编程结构_为什么系统编程全都用英文而不用中文?听完专家的解释恍然大悟!...
  7. python生成器迭代_python中的生成器和迭代器
  8. 中文域名销售平台_中国开关网.商城被搭建为南京某公司官网,这样的域名你喜欢吗?...
  9. 回环设备(loop-back devices)
  10. select EINTR