地下迷宫

来源:互联网 发布:形态学分水岭算法 编辑:程序博客网 时间:2024/04/27 23:31
题目描述
小青蛙有一天不小心落入了一个地下迷宫,小青蛙希望用自己仅剩的体力值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!"。
测试数据保证答案唯一
示例1
输入

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]


思路:该题考虑用bfs,定义一个二维数组dis记录走到当前位置剩余的最大能量。

#include<iostream>#include<queue>#include<iomanip>#include<vector>#include<unordered_map>#define N 10using namespace std;int n, m, p;int map[N][N];int dis[N][N];int pre[N][N];int dir[4][3] = { { 0, 1, 1 }, { 0, -1, 1 }, { 1, 0, 0 }, { -1, 0, 3 } };struct Point{int x;int y;int energy;Point(int _x = 0, int _y = 0, int _en = 0) :x(_x), y(_y), energy(_en){}Point go(int i){return Point(x + dir[i][0], y + dir[i][1], energy - dir[i][2]);}bool OK(){return  x >= 0 && x < n&&y >= 0 && y < m&&map[x][y] && energy >= 0;}};void show(){cout << "dis" << endl;for (int i = 0; i < n; i++){for (int j = 0; j < m; j++)cout<<setiosflags(ios::right)<<setw(4) << dis[i][j] ;cout << endl;}}void show1(){cout << "pre" << endl;for (int i = 0; i < n; i++){for (int j = 0; j < m; j++)cout << setiosflags(ios::right) << setw(4) << pre[i][j];cout << endl;}}int main(){while (cin >> n >> m >> p){for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)cin >> map[i][j];Point start(0, 0, p), end(0, m - 1, 0);fill(dis[0], dis[N - 1] + N, 0);fill(pre[0], pre[N - 1] + N, -1);dis[0][0] = p;//出发点的能量值queue<Point>q;vector<vector<int>>path;q.push(start);while (!q.empty()){Point tp = q.front();q.pop();cout << "cur i=" << tp.x << " " << tp.y << endl;for (int i = 0; i < 4; i++){Point next = tp.go(i);//尝试走下一步if (next.OK())//下一步可以走{if (dis[next.x][next.y] <= dis[tp.x][tp.y] - dir[i][2])//如果下一步的能量值比目前存储的高,说明上一步不是最优的,因此换成最优的{dis[next.x][next.y] = dis[tp.x][tp.y] - dir[i][2];next.energy = dis[next.x][next.y];q.push(next);pre[next.x][next.y] = tp.x*m + tp.y;//记录该节点的上一个节点}}}//show();//show1();}if (pre[0][m - 1] == -1){cout << "Can not escape!" << endl;}else{int x = 0, y = m - 1;vector<int>tv = { x, y };path.push_back(tv);while (pre[x][y] != -1){int temp = pre[x][y];x = temp / m;y = temp%m;//cout << "i=" << x << " j=" << y << endl;vector<int>tv = { x, y };path.push_back(tv);}for (int i = path.size() - 1; i > 0; i--){cout << "[" << path[i][0] << "," << path[i][1] << "],";}cout << "[" << path[0][0] << "," << path[0][1] << "]" << endl;}}}