地下迷宫

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值