算法竞赛入门经典:第六章 数据结构基础 6.12迷宫路径

/*
迷宫:
一个网格迷宫由n行m列单元格组成,每个单元格要么是空地(用1表示),要么是障碍物(用0表示)。你的任务是找一条从起点到终点的最短移动序列,其中UDLR分别
表示往上、下、左、右移动到相邻单元格。任何时候都不能在障碍格中,也不能走到迷宫之外。起点和终点保证是空地。n,m<=100。

思路:
从某点开始,计算出它到每个节点的最短距离,以及这些最短路径上每个节点的前一个节点
*/

/*
关键:
1 要设置父节点和从父节点到当前节点的走向,两个数组
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXSIZE 50
int queue[MAXSIZE*MAXSIZE];
//int father[MAXSIZE*MAXSIZE];
int father[MAXSIZE][MAXSIZE];
int dist[MAXSIZE][MAXSIZE];
int last_dir[MAXSIZE][MAXSIZE];//记录从父节点到子节点的移动序列
int dir[MAXSIZE*MAXSIZE];//方向序列
char name[MAXSIZE] = "RDLU";//方向解释
int iMark[MAXSIZE][MAXSIZE];
int iMaze[MAXSIZE][MAXSIZE];
int go[][2] = 
{
	{1,0},//0表示右
	{0,-1},//1表示往下
	{-1,0},//2表示往左
	{0,1}//3表示往上
};
int m;//列数
int n;//行数
int iEx,iEy;

void bfs(int x,int y)
{
	memset(iMark,0,sizeof(iMark));
	int front,rear,pos;
	front = rear = 0;
	pos = x*m + y;
	//置已经访问标记和父节点为本身,这个是后面递归的终止条件,距离为0表示,同时将队列中的首元素进行设置
	iMark[x][y] = 1;
	father[x][y] = pos;
	dist[x][y] = 0;
	queue[rear++] = pos;//这个元素,这里其实起到的作用是stat,因为这里无法保存状态,不过写得很搓,程序可读性差
	while(front < rear)
	{
		pos = queue[front++];
		x = pos/m;
		y = pos%m;
		for(int i = 0 ; i < 4 ;i++)
		{
			int iNextX = x + go[i][0];
			int iNextY = y + go[i][1];
			if(iNextX < n && iNextX >= 0 && iNextY < m && iNextY >= 0 && !iMark[iNextX][iNextY] && iMaze[iNextX][iNextY])//这里直接用成立的条件,进行操作,是改进
			{
				father[iNextX][iNextY] = pos;
				pos = iNextX*m + iNextY;
				queue[rear++] = pos;
				dist[iNextX][iNextY] = dist[x][y] + 1;
				last_dir[iNextX][iNextY] = i;
				if(iNextX == iEx && iNextY == iEy)//找到重点
				{
					return;
				}
			}
		}
	}
}

void printPath(int x,int y)//这里传入的x和y必须是最后一次走的节点,然后逆向推出其父节点
{
	int c = 0;
	for( ; ; )
	{
		int fx = father[x][y]/m;
		int fy = father[x][y]%m;
		if(x == fx && y == fy)
		{
			break;//如果没有父节点就退出,是退出条件
		}
		dir[c++] = last_dir[x][y];
		x = fx;
		y = fy;
	}
	while(c--)
	{
		printf("%c ",name[dir[c]]);
	}
}

void process()
{
	scanf("%d %d",&n,&m);
	scanf("%d %d",&iEx,&iEy);
	for(int i = 0 ; i < n ; i++)
	{
		for(int j = 0; j < m;j++)
		{
			scanf("%d",&iMaze[i][j]);
		}
	}
	bfs(0,0);
	//printPath(iEx,iEy);
	printPath(0,0);
}

/*
输入:
6 5
0 4
1 1 0 1 1
1 0 1 1 1
1 0 1 0 0
1 0 1 1 1 
1 1 1 0 1
1 1 1 1 1
输出:

*/

int main(int argc,char* argv[])
{
	process();
	system("pause");
	return 0;
}

你可能感兴趣的:(算法竞赛)