小青蛙走迷宫的问题

小青蛙有一天不小心落入了一个地下迷宫,小青蛙希望用自己仅剩的体力值P跳出这个地下迷宫。为了让问题简单,假设这是一个n*m的格子迷宫,迷宫每个位置为0或者1,0代表这个位置有障碍物,小青蛙达到不了这个位置;1代表小青蛙可以达到的位置。小青蛙初始在(0,0)位置,地下迷宫的出口在(0,m-1)(保证这两个位置都是1,并且保证一定有起点到终点可达的路径),小青蛙在迷宫中水平移动一个单位距离需要消耗1点体力值,向上爬一个单位距离需要消耗3个单位的体力值,向下移动不消耗体力值,当小青蛙的体力值等于0的时候还没有到达出口,小青蛙将无法逃离迷宫。现在需要你帮助小青蛙计算出能否用仅剩的体力值跳出迷宫(即达到(0,m-1)位置)。
输入描述:

输入包括n+1行:

第一行为三个整数n,m(3 <= m,n <= 10),P(1 <= P <= 100)

接下来的n行:

每行m个0或者1,以空格分隔

输出描述:

如果能逃离迷宫,则输出一行体力消耗最小的路径,输出格式见样例所示;如果不能逃离迷宫,则输出”Can not escape!”。
测试数据保证答案唯一

输入例子:
4 4 10
1 0 0 1
1 1 0 1
0 1 1 1
0 0 1 1
输出例子:
[0,0],[1,0],[1,1],[2,1],[2,2],[2,3],[1,3],[0,3]

分析:该问题属于迷宫求最短路径的问题!那么怎么求迷宫最短路径呢?

迷宫路径 、最短路径的问题:
迷宫路径:使用探测发,用一个栈保存路径;并且将上一个走过的路径标记。然后分别取探测改点的上、下、左、右是否可通,如果可通:递归进入该点,并把改点入栈;
递归的终止条件是到了出口(一般迷宫会规定出口);

最短路径的问题: 在上个问题的基础上我们定义个全局的数组 res;用来保存短路径。之后如果再次找到一条迷宫路径就和 res比较,如果他的size小于res,就把这条路径赋值给res

上代码:

#include<stdio.h>
#include<vector>

#include<iostream>
using namespace std;
//将位置封装成一个结构体,路径res存放的就是结构体
struct Node
{
  int x;
  int y;
};

int n,m,p,step = 999999;
vector<Node> res;//保存最优路径
int a[10][10];//定义了10*10大小的迷宫
bool is_visit[10][10] = { false };//标记走过的位置(true:已经走过;false:还没走过)

void findpath(vector<Node>& tmp, int energy, int i, int j)//运用了递归+上下探测的方法;
//如果当前位置的上、下、左、右可通,将其入栈,并且递归进去,并将当前位置标记;
//如果这条路不是最优路径或者不通,递归就会返回,再将该位置出栈,并把该位置的标记取消
{
  if(i == 0 && j == m-1)//走到了出口处
  {
    if(energy < p && energy < step)//判断改路径是否比上条路径更好(即比较消耗的能量)
    {
      step = energy;
      res = tmp;
    }
    return;
  }
  //上 
  if(i-1 >= 0 && a[i-1][j]== 1 && is_visit[i-1][j]==false)//如果这个位置合法,可通并且没有走过;则进入该位置
  {
    energy += 3;
    Node node;
    node.x = i-1;
    node.y = j;
    tmp.push_back(node);//将该位置入栈
    is_visit[i-1][j] = true;//标记为走过
    findpath(tmp, energy, i-1, j);
    energy -= 3;
    tmp.pop_back();//出栈
    is_visit[i-1][j] =false;//取消标记
  }
  //右
  if(j+1 < m && a[i][j+1] == 1 && is_visit[i][j+1] == false)
  {
    energy += 1;
    Node node;
    node.x = i;
    node.y = j+1;
    tmp.push_back(node);
    is_visit[i][j+1] = true;
    findpath(tmp, energy, i, j+1);
    energy -= 1;
    tmp.pop_back();
    is_visit[i][j+1] =false;
  }
  //下
  if(i+1 < n && a[i+1][j] == 1 && is_visit[i+1][j] == false)
  {
    energy += 0;
    Node node;
    node.x = i+1;
    node.y = j;
    tmp.push_back(node);
    is_visit[i+1][j] = true;
    findpath(tmp, energy, i+1, j);
    energy -= 0;
    tmp.pop_back();
    is_visit[i+1][j] = false;
  }
  //左
  if(j-1 >= 0 && a[i][j-1] == 1 && is_visit[i][j-1] == false)
  {
    energy += 1;
    Node node;
    node.x = i;
    node.y = j-1;
    tmp.push_back(node);
    is_visit[i][j-1] = true;
    findpath(tmp, energy, i, j-1);
    energy -= 1;
    tmp.pop_back();
    is_visit[i][j-1] = false;
  }
}

int main()
{
  cin>>n>>m>>p;
  for(int i = 0; i < n; ++i)
  {
    for(int j = 0; j < m; ++j)
      cin>>a[i][j];
  }

  vector<Node> tmp;
  int energy = 0;
  Node node;
  node.x = 0;
  node.y = 0;
  tmp.push_back(node);//将起点保存
  is_visit[0][0] = true;

  findpath(tmp, energy, 0, 0);

  if(step == 999999)
    cout<<"没有出路!";
  else 
  {
    int i = 0;
    for(i = 0; i < res.size()-1; ++i)
    {
      cout<<"["<<res[i].x<<","<<res[i].y<<"]"<<",";
    }
    cout<<"["<<res[i].x<<","<<res[i].y<<"]";
    cout<<endl;
  }

  return 0;
}

猜你喜欢

转载自blog.csdn.net/prefect_boy/article/details/81279242