poj 1556The Doors

本文探讨了如何解决在限定空间中找到两点间最短路径的问题,包括建图、路径查找算法(DIJ)的应用,以及考虑门与墙壁的特殊连接规则。详细解释了算法步骤和实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给一个房间,房间的边都是固定的,房间内有一些墙, 每面墙上有两个门, 起点是(0,5) 终点是(5,0), 求起点到终点的最短路径( 遇到墙从门走)


 解题思路:  想到怎么 建图就好做了

                       N条边则有4*N+1个顶点, 我们所要求的就是怎样连接这些定点使得起点到终点的距离最小

                       因为N最多是10,所以这道题完全可以暴力算点和点之间的距离,然后用 DIJ, 在建图的时候我们要注意 ,如果两个点连线跟门有交点, 那就意味着可以直接连接这两个点,并且根据题给要求得知相交一定是完全相交, 

                        用DIJ 的时候也要注意当松弛的时候得到的最小距离是起点到终点的最小距离那么直接返回就好了

                        PS 不知道为啥C++交就对G++就WA


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <stdlib.h>


using namespace std;
#define MAXP 555
#define MAXL 111
#define eps 1e-8
#define INF 100000000
double dis[MAXP], gra[MAXP][MAXP];
bool vis[MAXP];


struct Point
{
    double x,y;
    Point(){};
    Point(double a, double b)
    {
        x = a;
        y = b;
    }
}p[MAXP];


struct Line
{
    Point s, e;
    Line(){};
    Line(Point a, Point b)
    {
        s = a;
        e = b;
    }
}l[MAXL];


int sig(double a)
{
    if(a < -eps)
     return -1;
    if(a > eps)
     return 1;
    return 0;
}


double Across(Point a, Point b, Point c)
{
    return (b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x);
}


double getdis(Point a, Point b)
{
    return sqrt((a.x - b.x)*(a.x- b.x) + (a.y - b.y) * (a.y - b.y));
}


bool SegAcorss(Point a, Point b, Point c, Point d)
{
    int d1, d2, d3, d4;
    d1 = sig(Across(a, b, c));
    d2 = sig(Across(a, b, d));
    d3 = sig(Across(c, d, a));
    d4 = sig(Across(c, d, b));
    if(d1*d2 == -1 && d3*d4 == -1)
     return true;
    return false;
}


void solve(int pn, int ln)
{
    for( int i = 0; i <= pn; i++)
     for( int j = 0; j <= pn; j++)
         gra[i][j] = INF;


    for(int i = 0; i <= pn; i++)
    {
        for(int j = i + 1; j <= pn; j++)
        {
            bool flag  = 1;
            for(int k = 0; k < ln && flag; k += 2)
            {
                int t = 0,f[2] = {0};


                if(p[i].x < l[k].s.x && p[j].x > l[k].s.x)
                {
                    f[0] = SegAcorss(p[i],p[j], l[k].s, l[k].e);
                    f[1] = SegAcorss(p[i],p[j], l[k + 1].s, l[k+1].e);
                    t++;
                }
                if(t)
                flag = f[0]|f[1];


            }
            if(flag)
             gra[i][j] = getdis(p[i],p[j]);
        }
    }


}
double dij( int N )//求最短路
{
   for( int i = 0 ; i <= N ; i ++ )
   {
       vis[i] = false;
       dis[i] = 100000000;
   }
   dis[0] = 0;
   for( int i = 0 ; i < N ; i++ )
   {
      double min = 100000000;
      int t;
      for( int j = 0 ; j <= N ; j ++ )
      {
           if( !vis[j] && min > dis[j] )
           {
              min = dis[j] ; t = j;
           }
      }
      if( t==N ) return dis[N];
      vis[t] = true;
      for( int j = 0 ; j <= N ; j ++ )
      {
          if( !vis[j] && gra[t][j] != INF && dis[j] > dis[t] + gra[t][j] )
               dis[j] = dis[t] + gra[t][j];
      }
   }


   return dis[N];
}
int main()
{


    int n;
    double a,b,c,d,e;
    while(scanf("%d",&n)!= EOF && n != -1)
    {
        p[0].x = 0, p[0].y = 5;
        p[4*n+1].x = 10, p[4*n+1].y = 5;
        int lcnt = 0;
        for(int i = 0; i < n; i++)
        {
            scanf("%lf %lf %lf %lf %lf",&a, &b, &c, &d, &e);
            p[4*i + 1] = Point(a, b);
            p[4*i + 2] = Point(a, c);
            p[4*i + 3] = Point(a, d);
            p[4*i + 4] = Point(a, e);
            l[lcnt++] = Line(Point(a,b), Point(a,c));
            l[lcnt++] = Line(Point(a,d), Point(a,e));
        }
        solve(4*n + 1, lcnt);
        printf("%.2lf\n",dij(4*n+1));
    }
    return 0;
}

       



   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值