The Doors

Time Limit: 1000MS Memory Limit: 10000K

Description

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.

2

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

Source

Mid-Central USA 1996

一道相对来说偏综合的简单题,我们将墙拆成两个点,然后这道题的样例图示给了我们很好的思路:样例图示中整张图被巧妙地搞成了一张类分层图,而题目又让我们求从s" role="presentation" style="position: relative;">ss到t" role="presentation" style="position: relative;">tt的最短路径,题目中还巧妙地回避了有负边权的情况。既然这样,我们怎么可能不用dijstra" role="presentation" style="position: relative;">dijstradijstra来跑最短路呢?然后就是建图的问题了,最开始我想到的是相邻两层之间建边,但仔细一想这样会gg" role="presentation" style="position: relative;">gggg,于是改进一下建边的方法,对于每一个点,我们将它跟在它后面出现的点连边,边权的处理也很简单。如果两点之间可以直接抵达没有墙的间隔,那么直接将边权赋值为两点间的距离即可,如果有墙的间隔,我们不建边或者将边权赋成极大值,建完图之后跑最短路计算就行了。

然后还有一个坑点就是POJ" role="presentation" style="position: relative;">POJPOJ上用g++" role="presentation" style="position: relative;">g++g++的话double" role="presentation" style="position: relative;">doubledouble的输出只能用" role="presentation" style="position: relative;">(本蒟蒻因为这一点挂了10+" role="presentation" style="position: relative;">10+10+次)

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cmath>
#define N 100005
#define eps 1e-15
using namespace std;
struct pot{double x,y;}p[N];
struct edge{int v,next;double w;}e[N];
struct line{pot a,b;}l[N];
struct heap{int u;double w;};
inline bool operator<(heap a,heap b){return a.w>b.w;}
int n,first[N],cnt=0,s,t,tot=0,totx=0;
double d[N];
bool vis[N];
inline void add(int u,int v,double w){
    e[++cnt].v=v;
    e[cnt].next=first[u];
    e[cnt].w=w;
    first[u]=cnt;
}
inline double dijsktra(){
    priority_queue<heap>q;
    for(int i=0;i<=tot;++i)d[i]=10000000000.0,vis[i]=false;
    d[s]=0.0;
    q.push((heap){s,d[s]});
    while(!q.empty()){
        heap x=q.top();
        q.pop();
        if(vis[x.u])continue;
        vis[x.u]=true;
        for(int i=first[x.u];i!=-1;i=e[i].next){
            int v=e[i].v;
            if(d[v]>d[x.u]+e[i].w){
                d[v]=d[x.u]+e[i].w;
                q.push((heap){v,d[v]});
            }
        }
    }
    return d[t];
}
inline double dis(pot a,pot b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
inline pot operator-(pot a,pot b){return (pot){a.x-b.x,a.y-b.y};}
inline double cross(pot a,pot b){return a.x*b.y-a.y*b.x;}
inline int sign(double x){return (x>eps)-(x<-eps);}
inline bool pd(pot a,pot b,pot c,pot d){return sign(cross(a-c,b-c))*sign(cross(a-d,b-d))<0;}
inline bool check(int a,int b){
    for(int i=1;i<=totx;++i)if(pd(p[a],p[b],l[i].a,l[i].b)&&pd(l[i].a,l[i].b,p[a],p[b]))return false;
    return true;
}
int main(){
    p[s=0].x=0.0,p[s].y=5.0;
    while(scanf("%d",&n)&&n!=-1){
        memset(first,-1,sizeof(first));
        cnt=0,tot=0,totx=0;
        for(int i=1;i<=n;++i){
            double x0,y1,y2,y3,y4;
            scanf("%lf%lf%lf%lf%lf",&x0,&y1,&y2,&y3,&y4);
            p[++tot].x=x0,p[tot].y=0.0;
            p[++tot].x=x0,p[tot].y=y1;
            p[++tot].x=x0,p[tot].y=y2;
            p[++tot].x=x0,p[tot].y=y3;
            p[++tot].x=x0,p[tot].y=y4;
            p[++tot].x=x0,p[tot].y=10.0;
            l[++totx].a=(pot){x0,0.0},l[totx].b=(pot){x0,y1};
            l[++totx].a=(pot){x0,y2},l[totx].b=(pot){x0,y3};
            l[++totx].a=(pot){x0,y4},l[totx].b=(pot){x0,10.0};
        }
        p[t=++tot].x=10.0,p[t].y=5.0;
        for(int i=s;i<=t;++i)
            for(int j=i+1;j<=t;++j)
                if(check(i,j))add(i,j,dis(p[i],p[j]));
                else add(i,j,10000000000.0);
        printf("%.2lf\n",dijsktra());
    }
    return 0;
}

最新文章

  1. runtime梳理。
  2. jQuery倒计时
  3. robotframework笔记7
  4. CF 2013-2014CTS01E04(Killer Challenge-将质因数存在 进行Bitmask)
  5. 0x1L
  6. 用CAGradientLayer实现渐变色动画
  7. 4句代码读取Excel到DataSet(非Excel组件)
  8. cocos2d-js(一)引擎的工作原理和文件的调用顺序
  9. ng7 设置文件路径别名
  10. 运行python “没有那个文件或目录3” 或 “/usr/local/bin/python3^M: bad interpreter: 没有那个文件或目录” 错误
  11. ibm产品系列架构师技术路线
  12. 【分布式缓存系列】Redis实现分布式锁的正确姿势
  13. elk-(七)
  14. MySQL基础和JDBC
  15. Android中服务的生命周期与两种方式的区别
  16. Gradle Build Tool
  17. angularjs 在 iframe 里面无法正确显示 src 指定的内容
  18. Ionic2开发环境搭建、项目创建调试与Android应用的打包、优化
  19. CountDownLatch的和CyclicBarrier使用
  20. 8 个基于 Lucene 的开源搜索引擎推荐

热门文章

  1. 5.Struts2配置形式,覆盖
  2. 关联github, 添加gitignore 规则
  3. canal 常用配置
  4. vue基础——组件基础
  5. centos sendmail 启动慢
  6. Centos7搭建pptp一键安装脚本
  7. Unified shader model
  8. Haskell语言学习笔记(23)MonadReader, Reader, ReaderT
  9. 刚刚安装完nginx,服务启动,通过浏览器无法访问的问题
  10. 在SQL Server中使用CLR调用.NET方法