The Doors

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 xcoordinates 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 file 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

大意:在一个(10*10)平面内,求出发点(0,5)到终点(10,5) 的最短距离。

主要是用到了叉积判断线段是否相交,加上构图求最短路。

网上摘下来的代码,手打代码能力真的非常弱——老师为何丧心病狂叫一个提高一等都不稳的人做计算几何!!!虽然这个题目不难。。

#include <iostream>  

#include <cstdlib>  

#include <cstdio>  

#include <cstring>  

#include <cmath>  

#include <iomanip>  

using namespace std;  

  

const double maxdist=0x7FFFFFFF;  

int wall_num;  

int edge_num;  

int point_num;  

double precision=0.00000001;//用来控制判断精度  

double dist[100];  

double point_dist[100][100];  

struct edge_node{  

  double x1,x2,y1,y2;  

}edge[80];  

struct point_node{  

  double x,y;  

}point[100];  

  

/* 

 *在边的集合里添加边 

 *在点的集合里添加点 

 */  

void add_edge(double x1,double y1,double x2,double y2){  

  edge[edge_num].x1=x1;  

  edge[edge_num].x2=x2;  

  edge[edge_num].y1=y1;  

  edge[edge_num].y2=y2;  

  ++edge_num;  

}  

void add_point(double x,double y){  

  point[point_num].x=x;  

  point[point_num].y=y;  

  point_num++;  

}  

  

/* 

 *使用dijkstra求两点之间 

 */  

void dijkstra(){  

  for (int i=1;i<point_num;i++)  

    dist[i]=maxdist;  

  bool reach[100];  

  memset(reach,true,sizeof(reach));  

  for (int i=1;i<=point_num;i++){  

    int pos;  

    double value=maxdist;  

    for (int j=0;j<point_num;j++)  

      if (dist[j]<value && reach[j]){  

    value=dist[j];  

    pos=j;  

      }  

    reach[pos]=false;  

    for (int j=0;j<point_num;j++)  

      if (reach[j] &&   

      dist[pos]+point_dist[pos][j]<dist[j]){  

    dist[j]=dist[pos]+point_dist[pos][j];  

      }  

  }  

}  

  

/* 

 *以下一连串子程序用叉积来判断两条线段是否相交 

 */  

double det(double x1,double y1,double x2,double y2){  

  return x1*y2-x2*y1;  

}  

double cross(point_node a,point_node b,point_node c){  

  return det(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);  

}  

int cmp(double d){  

  if (fabs(d)<precision)  

    return 0;  

  return (d>0)?1:-1;  

}  

bool segment_cross_simple(point_node a,point_node b,point_node c,point_node d){  

  if (((cmp(cross(a,c,d))^cmp(cross(b,c,d)))==-2)&&  

      ((cmp(cross(c,a,b))^cmp(cross(d,a,b)))==-2))  

    return true;  

  else  

    return false;  

}  

/* 

 *解决过程 

 */  

void solve(){  

  /* 

   *初始化过程 

   */  

  memset(edge,0,sizeof(edge));  

  memset(point,0,sizeof(point));  

  memset(dist,0,sizeof(dist));  

  memset(point_dist,0,sizeof(point_dist));  

  //点集和边集清零  

  edge_num=0;  

  point_num=0;  

  add_point(0,5);  

  add_point(10,5);  

  //增加起点和终点  

  for (int i=1;i<=wall_num;i++){  

    double x,y1,y2,y3,y4;  

    cin >> x >> y1 >> y2 >> y3 >> y4;  

      

    //输入每个墙,并添加墙所对应的边  

    add_edge(x,0,x,y1);  

    add_edge(x,y2,x,y3);  

    add_edge(x,y4,x,10);  

    //添加墙所对应的新增顶点  

    add_point(x,y1);  

    add_point(x,y2);  

    add_point(x,y3);  

    add_point(x,y4);  

  }  

    

  for (int i=0;i<point_num;i++)  

    for (int j=0;j<point_num;j++)//枚举任意两个点  

      if (i!=j){//如果他们不是同一个点  

    bool link=true;  

    for (int k=0;k<edge_num;k++){  

      point_node lv,lv2;  

      lv.x=edge[k].x1;lv.y=edge[k].y1;  

      lv2.x=edge[k].x2;lv2.y=edge[k].y2;  

      if (segment_cross_simple(point[i],point[j],lv,lv2))  

        link=false;  

    }  

    if (link)  

      point_dist[i][j]=sqrt(pow(point[i].x-point[j].x,2)+  

                pow(point[i].y-point[j].y,2));  

    else  

      point_dist[i][j]=maxdist;  

      }  

  //对于任意两个顶点求他们之间的路径  

  

  dijkstra();  

  //求出源点开始的dijkstra  

  

  cout << setiosflags(ios::fixed)   

       << setprecision(2)   

       << dist[1] << endl;   

}  

  

/* 

 *主过程 

 */  

int main(){  

  cin >> wall_num;  

  while (wall_num!=-1){  

    solve();  

    cin >> wall_num;  

  }  

}

UVA 393的更多相关文章

  1. Fast Matrix Operations(UVA)11992

    UVA 11992 - Fast Matrix Operations 给定一个r*c(r<=20,r*c<=1e6)的矩阵,其元素都是0,现在对其子矩阵进行操作. 1 x1 y1 x2 y ...

  2. uva 1354 Mobile Computing ——yhx

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABGcAAANuCAYAAAC7f2QuAAAgAElEQVR4nOy9XUhjWbo3vu72RRgkF5

  3. UVA 10564 Paths through the Hourglass[DP 打印]

    UVA - 10564 Paths through the Hourglass 题意: 要求从第一层走到最下面一层,只能往左下或右下走 问有多少条路径之和刚好等于S? 如果有的话,输出字典序最小的路径 ...

  4. UVA 11404 Palindromic Subsequence[DP LCS 打印]

    UVA - 11404 Palindromic Subsequence 题意:一个字符串,删去0个或多个字符,输出字典序最小且最长的回文字符串 不要求路径区间DP都可以做 然而要字典序最小 倒过来求L ...

  5. UVA&&POJ离散概率与数学期望入门练习[4]

    POJ3869 Headshot 题意:给出左轮手枪的子弹序列,打了一枪没子弹,要使下一枪也没子弹概率最大应该rotate还是shoot 条件概率,|00|/(|00|+|01|)和|0|/n谁大的问 ...

  6. UVA计数方法练习[3]

    UVA - 11538 Chess Queen 题意:n*m放置两个互相攻击的后的方案数 分开讨论行 列 两条对角线 一个求和式 可以化简后计算 // // main.cpp // uva11538 ...

  7. UVA数学入门训练Round1[6]

    UVA - 11388 GCD LCM 题意:输入g和l,找到a和b,gcd(a,b)=g,lacm(a,b)=l,a<b且a最小 g不能整除l时无解,否则一定g,l最小 #include &l ...

  8. UVA - 1625 Color Length[序列DP 代价计算技巧]

    UVA - 1625 Color Length   白书 很明显f[i][j]表示第一个取到i第二个取到j的代价 问题在于代价的计算,并不知道每种颜色的开始和结束   和模拟赛那道环形DP很想,计算这 ...

  9. UVA - 10375 Choose and divide[唯一分解定理]

    UVA - 10375 Choose and divide Choose and divide Time Limit: 1000MS   Memory Limit: 65536K Total Subm ...

随机推荐

  1. NYOJ之Binary String Matching

    Binary String Matching 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述     Given two strings A and B, whose a ...

  2. python中random模块使用

  3. Asp.Net - 8.多线程

    8.1 概念 进程(Process):是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源.进程之间是相对独立的,一个进程无法直接访问另一个进程的数据(除非利用分布式计算方式),一个 ...

  4. WCF分布式开发必备知识(2):.Net Remoting

    .Net Remoting技术,我们可以将其看作是一种分布式处理方式.作为应用程序之间通信的一种机制,.Net Remoting与MSMQ消息队列不同,它不支持离线脱机消息,另外只适合.Net平台间程 ...

  5. 【PHP对XML文件的操作技术【完整版】】

    无论是c/c++还是java.c#均有对XML文件操作的技术,PHP对XML文件的操作的技术主要有三种: DOM.XPath.SimpleXml. 一.DOM DOM:Document Object ...

  6. 图结构练习——最小生成树(prim算法(普里姆))

      图结构练习——最小生成树 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述  有n个城市,其中有些城市之间可以修建公路,修建不同 ...

  7. 【20140113】package 与 import

    一个完整的java源程序应该包括下列部分: package语句: //该部分至多只有一句,必须放在源程序的第一句 import语句: public classDefinition: //公共类定义部分 ...

  8. 在 Android Studio中恢复已经被移除的Module

    假设名为app的Module已经被移除,则他的图标上小手机图标将会消失.此时如下图编辑settings.gradle,然后点击如图按钮Sync Project with Gradle Files即可. ...

  9. hdu 5033 单调栈 ****

    看出来是单调栈维护斜率,但是不会写,2333,原来是和询问放在一起的 #include <iostream> #include <cstdio> #include <cs ...

  10. 第二十三篇:在SOUI中使用LUA脚本开发界面

    像写网页一样做客户端界面可能是很多客户端开发的理想. 做好一个可以实现和用户交互的动态网页应该包含两个部分:使用html做网页的布局,使用脚本如vbscript,javascript做用户交互的逻辑. ...