zoukankan      html  css  js  c++  java
  • UVA 393

    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;  
      }  


    Sometimes it s the very people who no one imagines anything of. who do the things that no one can imagine.
  • 相关阅读:
    由于版本依赖造成的YUM段错误
    CodeDom系列事件(event)定义和反射调用
    CodeSmith模板引擎系列二文件目录树
    F#初试打印目录文件树
    在IIS上SSL的部署和启动SSL安全
    CodeDom系列二程序基本结构符号三角形问题
    CodeDom系列目录
    CodeDom系列四Code生成
    CodeDom六实体类生成示例
    CodeDom系列五动态编译
  • 原文地址:https://www.cnblogs.com/YCuangWhen/p/5188098.html
Copyright © 2011-2022 走看看