zoukankan      html  css  js  c++  java
  • 一本通1251:仙岛求药

    【题目描述】

    少年李逍遥的婶婶病了,王小虎介绍他去一趟仙灵岛,向仙女姐姐要仙丹救婶婶。叛逆但孝顺的李逍遥闯进了仙灵岛,克服了千险万难来到岛的中心,发现仙药摆在了迷阵的深处。迷阵由M×N个方格组成,有的方格内有可以瞬秒李逍遥的怪物,而有的方格内则是安全。现在李逍遥想尽快找到仙药,显然他应避开有怪物的方格,并经过最少的方格,而且那里会有神秘人物等待着他。现在要求你来帮助他实现这个目标。

    下图 显示了一个迷阵的样例及李逍遥找到仙药的路线。

    【输入】

    输入有多组测试数据. 每组测试数据以两个非零整数 M 和 N 开始,两者均不大于20。M 表示迷阵行数, N 表示迷阵列数。接下来有 M 行, 每行包含N个字符,不同字符分别代表不同含义:

    1)‘@’:少年李逍遥所在的位置;

    2)‘.’:可以安全通行的方格;

    3)‘#’:有怪物的方格;

    4)‘*’:仙药所在位置。

    当在一行中读入的是两个零时,表示输入结束。

    【输出】

    对于每组测试数据,分别输出一行,该行包含李逍遥找到仙药需要穿过的最少的方格数目(计数包括初始位置的方块)。如果他不可能找到仙药, 则输出 -1。

    【输入样例】

    8 8
    .@##...#
    #....#.#
    #.#.##..
    ..#.###.
    #.#...#.
    ..###.#.
    ...#.*..
    .#...###
    6 5
    .*.#.
    .#...
    ..##.
    .....
    .#...
    ....@
    9 6
    
    .#..#.
    .#.*.#
    .####.
    ..#...
    ..#...
    ..#...
    ..#...
    #.@.##
    .#..#.
    0 0

    【输出样例】

    10
    8
    -1

    一看到这样的问题肯定就是搜索了
    主函数建图,再定义一个搜索函数
    说干就干
    先看这“仙境”是由什么构成的吧
    “@”表示李逍遥所在的位置,也就是搜索的起点;
    “.”则表示可以经过的格子;
    “#”表示不能过去否则会被妖怪打死的格子;
    “*”表示整条路径的终点;
    拿一组输入数据来说
    首先通过读入的m,n定义一个二维数组p[m][n];
    再定义两个一维数组,每个有四个元素,表示搜索时的四个方向;
    循环输入每个字符;
    并同时给出一个与p数组一一对应的二维bool数组表示能否经过;
    最后定义搜索的起点和终点;
    代码如下
    int n,m,x,y,qx,qy;
    int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};//定义了搜索的方向
    int p[10001][4];//表示某一个点的横坐标,纵坐标和到当前点的步数
    char k;
    bool b[101][101];
    ———————————————————————————————    
    if(m==0&&n==0)
                return 0;
                memset(p,0,sizeof(p));
                memset(b,true,sizeof(b));
                for(int i=1;i<=m;i++)
                {
                    for(int j=1;j<=n;j++)//两层循环输入地图
                    {
                        cin>>k;
                        if(k=='#')//判断不能走的格子
                        b[i][j]=false;
                        else b[i][j]=true; 
                        if(k=='@')//定义起点的p数组
                        {
                            p[1][1]=i;
                            p[1][2]=j;
                            p[1][3]=0;
                            b[i][j]=false;
                        }
                        if(k=='*')//定义终点和搜索停止条件
                        {
                            qx=i;
                            qy=j;
                        }
                    }
                }
    现在图建好了;下面就是激动人心的搜索部分

    看着代码,我们分析一下搜索部分代码的共同点;

    void bfs()//定义广搜函数
    {
         int t=0,w=1;
         while(t<w)
         {
         t++;
         for(int i=0;i<4;i++)//对一个点的搜索,四个方向
         {
             x=p[t][1]+dx[i];
             y=p[t][2]+dy[i];//上面两行是横纵坐标的变化
             if(x>0&&x<=m&&y>0&&y<=n&&b[x][y])//判断边界条件,X>0和y>0不必多说
             //x<=m和y<=n则是判断边界条件,b[x][y]则是判断能不能走或者走过没有
             {
             w++;//满足上面的条件就可以对这个新的点进行搜索
             p[w][1]=x;//把这个点的横坐标定义为x
             p[w][2]=y;//把这个点的纵坐标定义为y
             p[w][3]=p[t][3]+1;//经过该点,步数+1
             b[x][y]=false;//标记该点为走过
             if(x==qx&&y==qy)//判断这个点是否为终点
             {
                 printf("%d
    ",p[w][3]);//终点则输出步数
                 return;//搜索结束
             }
            }
         }
         }
         printf("-1
    ");//到不了就输出-1
    }

    一般搜索函数异曲同工,这一段是所有搜索函数都必要的

    for(int i=0;i<4;i++)
         {
             x=p[t][1]+dx[i];
             y=p[t][2]+dy[i];
             if(x>0&&x<=m&&y>0&&y<=n&&b[x][y])
             {
             w++;
             p[w][1]=x;
             p[w][2]=y;
             p[w][3]=p[t][3]+1;
             b[x][y]=false;
             if(x==qx&&y==qy)
             {
                 printf("%d
    ",p[w][3]);
                 return;
             }
            }
         }

    简单来说就是

    对现在所在的点进行是四个方向的搜索;

    会生成四个不同的坐标;

    每个新生成的坐标都要判断是否超过边界或者已经被标记为false;

    如果是个能够搜索的坐标;

    那么我们就到这个点上去,把我们所在的点的坐标更新为这个新产生的点;

    并且所走的步数加一;

    再把这个点标记成已经走过;

    如果这个点是终点;

    那么搜索结束并输出步数;

    如果不是;

    那么一直往下搜索到不能在搜索或者找到终点为止。


    我们来看一下完整的AC代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    using namespace std;
    int n,m,x,y,qx,qy;
    int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1},p[10001][4];
    char k;
    bool b[101][101];
    void bfs()
    {
         int t=0,w=1;
         while(t<w)
         {
         t++;
         for(int i=0;i<4;i++)
         {
             x=p[t][1]+dx[i];
             y=p[t][2]+dy[i];
             if(x>0&&x<=m&&y>0&&y<=n&&b[x][y])
             {
             w++;
             p[w][1]=x;
             p[w][2]=y;
             p[w][3]=p[t][3]+1;
             b[x][y]=false;
             if(x==qx&&y==qy)
             {
                 printf("%d
    ",p[w][3]);
                 return;
             }
            }
         }
         }
         printf("-1
    ");
    }
    int main()
    {
            while(cin>>m>>n)
            {
                if(m==0&&n==0)
                return 0;
                memset(p,0,sizeof(p));
                memset(b,true,sizeof(b));
                for(int i=1;i<=m;i++)
                {
                    for(int j=1;j<=n;j++)
                    {
                        cin>>k;
                        if(k=='#')
                        b[i][j]=false;
                        else b[i][j]=true; 
                        if(k=='@')
                        {
                            p[1][1]=i;
                            p[1][2]=j;
                            p[1][3]=0;
                            b[i][j]=false;
                        }
                        if(k=='*')
                        {
                            qx=i;
                            qy=j;
                        }
                        
                    }
                }
                bfs();
            }
    }

    是不是很简单?(bushi

    总体来说搜索的问题基本上就是建图与搜索;

    搜索函数异曲同工;

    建图的方式和各种符号各自表示的内容题干也已给出;

    两者都并不是什么难事;

    多打几个例题就能发现其中的规律和骨架;

    发现搜索的本质就是标记记录然后循环。


    祝你我早日AKIOI

  • 相关阅读:
    求周期串的最小正周期
    Manacher's Algorithm
    高精度
    找x的两个素数因子使x=pq(Pollard_Rho)
    Intersection is not allowed!
    类欧几里得
    分数规划
    'sessionFactory' or 'hibernateTemplate' is required
    Struts2的动态方法,及result跳转方式,全局结果以及默认的action的配置
    配置Struts2及Struts2访问servlet api的方式
  • 原文地址:https://www.cnblogs.com/Jiangxingchen/p/12905611.html
Copyright © 2011-2022 走看看