zoukankan      html  css  js  c++  java
  • POJ 1556 The Doors 线段判交+Dijkstra

    The Doors
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 6734   Accepted: 2670

    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. 


    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

    题目大意: 给定有多少个墙,每个墙有两个门,问从(0, 5)->(10, 5)这个点的最短距离是多少,不能穿墙而过

    解题思路: 既然是求最短路径的,那就转化到最短路径来算. 关键是怎么转化问题. 因为每个门都有可能成为必须要走的路线,而且每个门都有两个端点. 所以只需要枚举每个端点就行了.如果任意两个短线没有墙阻挡,那么就是可以直达的, 就把他加到图中,如果有墙阻隔,那么就是不直接可达.所以图的建立就是遍历所有的端点,包括起始点和终点.

    /*************************************************************************
        > File Name: poj_1556.cpp
        > Author: 
        > Mail: 
        > Created Time: 2015年04月02日 星期四 14时55分17秒
     ************************************************************************/
    
    #include<iostream>
    #include <cstdio>
    #include <cstring>
    #include <math.h>
    using namespace std;
    const int N = 100;
    const int INF = 99999999;
    struct point{
        double x, y;
    };
    point p[N];
    double dis[N];
    double Map[N][N];
    bool vis[N];
    int n;
    double getDistance(int i, int j)//得到两个点之间的距离
    {
        return sqrt((p[i].x - p[j].x) * (p[i].x - p[j].x) + (p[i].y - p[j].y) * (p[i].y - p[j].y));
    }
    double getDirection(point a, point b, point c)//判断c与直线ab的关系
    {
        point t1, t2;
        t1.x = c.x - a.x; t1.y = c.y - a.y;
        t2.x = b.x - a.x; t2.y = b.y - a.y;
        return (t1.x * t2.y - t1.y * t2.x);
    }
    bool segment_intersect(point a, point b, point c, point d)//判断线段是否相交
    {
        double d1 = getDirection(a, b, c);
        double d2 = getDirection(a, b, d);
        double d3 = getDirection(c, d, a);
        double d4 = getDirection(c, d, b);
        if (d1 * d2 < 0 && d3 * d4 < 0)
            return true;
        return false;
    }
    bool isCross(int a, int b)//判断两点之间是否有墙阻隔
    {
        point t1, t2;
        int i;
        if (a == 0)
            i = 1;
        else
            i = a / 4 + (a % 4 != 0) + 1;
        for (; i < b / 4 + (b % 4 != 0); i++)
        {
            t1.x = p[4 * i - 3].x;
            t1.y = 0;
            t2.x = t1.x; t2.y = 10.0;
            if (segment_intersect(t1, p[4 * i - 3], p[a], p[b]) || segment_intersect(p[4 * i - 2], p[4 * i - 1], p[a], p[b]) 
                || segment_intersect(p[4 * i], t2, p[a], p[b]))
                return true;
    
        }
        return false;
    }
    void Dijkstra()//单源最短路径
    {
        memset(vis, false, sizeof(vis));
        int m = 4 * n + 2;
        for (int i = 0; i < m; i++)
            dis[i] = Map[0][i];
        dis[0] = 0;
        vis[0] = true;
        double min;
        int k;
        for (int i = 1; i < m; i++)
        {
            min = INF;
            for (int j = 0; j < m; j++)
            {
                if (!vis[j] && min > dis[j])
                {
                    k = j;
                    min = dis[j];
                }
            }
            vis[k] = true;
            for (int j = 0; j < m; j++)
            {
                if (!vis[j] && dis[j] > dis[k] + Map[k][j])
                    dis[j] = dis[k] + Map[k][j];
            }
            
        }
    }
    int main()
    {
        while (~scanf("%d", &n) && n != -1)
        {
            double a, b, c, d, e;
            p[0].x = 0; p[0].y = 5;
            p[4 * n + 1].x = 10; p[4 * n + 1].y = 5;//一共4*n+2个点
            for (int i = 1; i <= 4 * n; i++)
            {
                scanf("%lf %lf %lf %lf %lf", &a, &b, &c, &d, &e);
                p[i].x = a; p[i].y = b;
                p[++i].x = a; p[i].y = c;
                p[++i].x = a; p[i].y = d;
                p[++i].x = a; p[i].y = e;
            }
            for (int i = 0; i < 4 * n + 2; i++)
            {
                for (int j = 0; j < 4 * n + 2; j++)
                    if (i != j)
                        Map[i][j] = INF;
                    else
                        Map[i][j] = 0;
            }
            for (int i = 0; i < 4 * n + 2; i++)//建立地图
            {
                for (int j = i + 1; j < 4 * n + 2; j++)
                {
                    if (!isCross(i, j))
                        Map[i][j] = getDistance(i, j);
                }
            }
            Dijkstra();//求最短路径
            printf("%.2f
    ", dis[4 * n + 1]);
    
        }
    
    
        return 0;
    }
    View Code
  • 相关阅读:
    错误滚动条eclipse快速定位到错误处
    路径原因linux下tomcat无法启动
    提示命令命令行将U盘文件系统转换成ntfs
    客户传真第四部分 个人理财风险防范8.当心银行汇款引发的诈骗
    请求错误[Python]网络爬虫(三):异常的处理和HTTP状态码的分类
    范围元【2013 GDCPC】有为杯 广东ACM省赛小总结
    编程程序国外程序员的BASIC情结——我的编程生涯始于BASIC
    执行取消利用timer实现的倒计时
    文件分析IDA反汇编/反编译静态分析iOS模拟器程序(二)加载文件与保存数据库
    安全业务第四部分 个人理财风险防范9.取款也要加小心
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/4388421.html
Copyright © 2011-2022 走看看