题目描述
小青蛙有一天不小心落入了一个地下迷宫,小青蛙希望用自己仅剩的体力值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
输出
小青蛙有一天不小心落入了一个地下迷宫,小青蛙希望用自己仅剩的体力值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 10
using 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;
}
}
}