• 【最短路】Maze


    版权声明:本篇随笔版权归作者Etta(http://www.cnblogs.com/Etta/)所有,转载请保留原地址!

    问题描述:

      小鼠a与小鼠b身处一个m×n的迷宫中,如图所示。每一个方格表示迷宫中的一个房间。这m×n个房间中有一些房间是封闭的,不允许任何人进入。在迷宫中任何位置均可沿上,下,左,右4个方向进入未封闭的房间。小鼠a位于迷宫的(p,q)方格中,它必须找出一条通向小鼠b所在的(r,s)方格的路。请帮助小鼠a找出所有通向小鼠b的最短道路。

    编程任务:

      对于给定的小鼠的迷宫,编程计算小鼠a通向小鼠b的所有最短道路。

    数据输入:

      由文件input.txt给出输入数据。第一行有3个正整数n,m,k,分别表示迷宫的行数,列数和封闭的房间数。接下来的k行中,每行2个正整数,表示被封闭的房间所在的行号和列号。最后的2行,每行也有2个正整数,分别表示小鼠a所处的方格(p,q)和小鼠b所处的方格(r,s)。

    结果输出:

      将计算出的小鼠a通向小鼠b的最短路长度和有多少条不同的最短路输出到文件output.txt。文件的第一行是最短路长度。文件的第2行是不同的最短路数。

    如果小鼠a无法通向小鼠b则输出“No Solution!”。

    Input:

    8 8 3

    3 3

    4 5

    6 6

    2 1

    7 7

    Output:

    11

    96

    一、分析问题

           看到这道题想起搜索里经典的走迷宫求路径,于是直接bfs求最短路dfs搜路径数,奈何一个点始终TLE。于是有另一个快且简洁的方法。把每一个格子抽象为一个点,相邻的点之间有长度为1的边,SPFA求最短路径,递推求最短路径数。

    二、解决问题

           SPFA+递推

    Tips:

    1.递推是难点

    if(dis[u]>dis[v]+1)f[u]=f[v];

    else if(dis[u]==dis[v]+1)f[u]+=f[v];//

    2.使用一维数组代替二维数组使得队列实现更加方便

           F[i,j]=>f[i*(m-1)+j]

    3.m*n的表格,m行n列//

    三、代码实现

     1 #include<cstdio>
     2 #include<queue>
     3 using namespace std;
     4 
     5 const int MA=100,inf=4e8;
     6 int m,n,k,st,en;
     7 int x,y,t,a,b,c,d;
     8 int dis[MA*MA],fa[MA*MA],ex[MA*MA];
     9 queue<int>p;
    10 
    11 int calc(int x,int y)
    12 {
    13     return (x-1)*m+y;
    14 }
    15 
    16 void spfa(int u,int v)
    17 {
    18     if(dis[u]>dis[v]+1)
    19     {
    20         fa[u]=fa[v];
    21         dis[u]=dis[v]+1;
    22         if(!ex[u])
    23         {
    24             p.push(u);
    25             ex[u]=1;
    26         }
    27     }
    28     else
    29     if(dis[u]==dis[v]+1)
    30     fa[u]+=fa[v];
    31 }
    32 
    33 void SPFA()
    34 {
    35     p.push(st);
    36     dis[st]=0;
    37     fa[st]=1;
    38     while(!p.empty())
    39     {
    40         int tmp=p.front();
    41         ex[tmp]=0;
    42         p.pop();
    43         if(tmp+m<=n*m&&dis[tmp+m]!=-1)spfa(tmp+m,tmp);
    44         if(tmp-m>=0&&dis[tmp-m]!=-1)spfa(tmp-m,tmp);
    45         if(tmp%m!=0&&dis[tmp+1]!=-1)spfa(tmp+1,tmp);
    46         if(tmp%m!=1&&dis[tmp-1]!=-1)spfa(tmp-1,tmp);
    47     }
    48 }
    49 
    50 int main()
    51 {
    52     scanf("%d%d%d",&n,&m,&k);
    53     for(int i=1;i<=n*m;++i)dis[i]=inf;
    54     for(int i=1;i<=k;++i)
    55     {
    56         scanf("%d%d",&x,&y);
    57         t=calc(x,y);
    58         dis[t]=-1;
    59     }
    60     scanf("%d%d%d%d",&a,&b,&c,&d);
    61     st=calc(a,b);
    62     en=calc(c,d);
    63     
    64     SPFA();
    65     
    66     if(dis[en]==inf)printf("No Solution!
    ");
    67     else printf("%d
    %d
    ",dis[en],fa[en]);
    68     return 0;
    69 }
  • 相关阅读:
    CLR(Common Language Runtime)
    六个经典的英语面试问题
    XML基本知识(三)
    vc++中各种字符串(转载)
    winform窗体间传值
    jQuery实现按比例缩放图片
    .net中几个名词解释
    XML Schema 定义
    C#中TreeView组件使用方法初步
    微软电话面试题
  • 原文地址:https://www.cnblogs.com/Etta/p/6354204.html
Copyright © 2020-2023  润新知