小青蛙有一天不小心落入了一个地下迷宫,小青蛙希望用自己仅剩的体力值P跳出这个地下迷宫。为了让问 题简单,假设这是一个n*m的格子迷宫,迷宫每个位置为0或者1,0代表这个位置有障碍物,小青蛙达到不了这个

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

#define VISITED 2//标记已经访问过的结点

int n;//n行
int m;//n列
int P;//p个力气

int maze[10][10];//迷宫阵列

//假如一个坐标是(x,y),以下是坐标需要向左、右、上、下,坐标
//需要加的数,即如果向上走(x-1,y+0)
int dir[4][2] = { {0,-1},{0,1},{-1,0},{1,0} };

//向左、右、上、下分别需要加的体力值,如向上走,体力值需要
//减去3
int cost[4] = {-1,-1,-3,0};

int final_p = -200;//初始的体力剩余值(初始较小,保证会被更新)

//坐标点
struct maze_point
{
	int _x;
	int _y;
	maze_point(int x, int y)
		:_x(x)
		, _y(y)
	{}
};

vector<maze_point> path_stack;//存储每次遍历的路径
vector<maze_point> min_costpath;//存储最终的最优路径

//打印vector中的路径(vector每个元素是个坐标点maze_point)
void print_path(const vector<maze_point>& path)
{
	for (int i = 0; i < path.size(); i++)
	{
		cout << "[" << path[i]._x << "," << path[i]._y << "]";
		if (i < path.size() - 1)//每个坐标之间的间隔
		{
			cout << ",";
		}
	}
}

//主要的逻辑(寻找最优路径)
//参数是坐标点,当前体力值

void search(int x, int y, int cur_p)
{
	//将当前坐标加入路径,并且标记为已访问
	path_stack.push_back(maze_point(x, y));
	maze[x][y] = VISITED;

	//找到一条路径了,但是不要急,和上一条的剩余体力值比一比看哪一条更优
	if ((x == 0 && y == m - 1) && cur_p >= 0)
	{
		if (cur_p > final_p)//说明当前路径更优
		{
			final_p = cur_p;
			min_costpath = path_stack;
		}

		//将当前结点弹出,即回退找下一条路径
		path_stack.pop_back();
		maze[x][y] = 1;
		return;
	}

	//如果当前结点并非出口,则分别向左、右、上、下探索,
	//其中每个结点又当做一个节点探索其的左、右、上、下
	if (cur_p > 0)
	{
		for (int i = 0; i < 4; i++)
		{
			//更新移动后的坐标值
			int nx = x + dir[i][0];
			int ny = y + dir[i][1];

			//更新移动后的体力值
			int np = cur_p + cost[i];

			//如果更新后的坐标合法,并且该位置是1,即可走,则以该结点为主结点递归这个节点
			if (nx >= 0 && nx < n && ny >= 0 && ny < m && maze[nx][ny] == 1)
			{
				search(nx, ny, np);
			}
		}

		//来到这,说明该节点的四个方向都走不通,则该节点
		//不可能是路径上的一个,则弹出该节点
		path_stack.pop_back();
		maze[x][y] = 1;
	}
}

猜你喜欢

转载自blog.csdn.net/lyl194458/article/details/89331240
今日推荐