北大 acm 3083解题报告--dfs与bfs的运用

    题目:http://poj.org/problem?id=3083

    题目的大意就是:输入一个类似迷宫的东西,其中S表示起点,E表示终点,#表示墙壁,,表示空地。其中S,E一定在边缘,并且S一定能到达E

    例如:    

  ########
  #......#
  #.####.#
  #.####.#
  #.####.#
  #.####.#
  #...#..#
  #S#E####

    求人从S出发,到达E的过程需要走几步?走的方式有三种,靠左走,靠右走,以及最短路径的走法,分别输出步数

    以上面的输入为例,靠左走:37步; 靠右走:5步; 最短:5步

    最短路径的肯定采用bfs;

    重点理解是靠左走,靠右走;

    假设我们 下 ,左 ,上 ,右  四个方向编号为 0,1 , 2,3

   靠左走分四种情况:

    (1)目前的行走朝向是  上 ,则考虑的朝向的优先级(由高到低),左,上,右,下   ; 对应编号: 2 ,    1   2  3  0

    (2)目前的行走朝向是  下  ,则考虑的朝向的优先级(由高到低),右,下,左,上   ;对应编号: 0 ,    3   0  1  2

    (3)目前的行走朝向是  右  ,则考虑的朝向的优先级(由高到低),上,右,下,左   ;对应编号: 3 ,    2   3  0  1

    (4)目前的行走朝向是  左  ,则考虑的朝向的优先级(由高到低),下,左,上,右  ; 对应编号:  1 ,    0  1   2  3

  靠右走分四种情况:

    (1)目前的行走朝向是  上 ,则考虑的朝向的优先级(由高到低),右,上,左,下   ;对应编号: 2 ,    3   2  1  0

    (2)目前的行走朝向是  下  ,则考虑的朝向的优先级(由高到低),左,下,右,上  ;对应编号: 0 ,    1   0  3  2

    (3)目前的行走朝向是  右  ,则考虑的朝向的优先级(由高到低),下,右,上,左  ;对应编号: 3 ,    0   3  2  1

    (4)目前的行走朝向是  左  ,则考虑的朝向的优先级(由高到低),上,左,下,右 ;对应编号:  1 ,    2   1  0  3

    假设当前的朝向编号为m,朝向的编号最高优先级为n;

    则:

    靠左走:n=(m+3)%4;    n=(n+1)%4;

    靠右走:n=(m+1)%4;    n=(n+3)%4;

    源码实现如下:

   

//3083
#include<iostream>
#include <cstring>
using namespace std;

const int N=45;
typedef struct _node
{
	int x;
	int y;
}Node;
char maze[N][N];
int  visited[N][N];
int  dir[4][2]={{1,0},{0,-1},{-1,0},{0,1}};
int  w,h;
Node Q[N*N];
int  Pre[N][N][2];
int  direct;

bool ldfs(int x, int y, int step)  
{
	if (maze[x][y] == 'E')
	{
		cout<<step<<" ";
		return true;
	}
	direct = (direct + 3) % 4;    //靠左手边走
	while(1)
	{
		int tmpx=x + dir[direct][0];
		int tmpy=y + dir[direct][1];
		if (tmpx<h&&tmpx>=0&&tmpy<w&&tmpy>=0)
		{
			if (maze[tmpx][tmpy]=='.'||maze[tmpx][tmpy]=='E')
			{
				if(ldfs(tmpx, tmpy, step + 1)) return true;
			}
		}
	direct = (direct + 1) % 4;   //顺时针
	}
}
bool rdfs(int x, int y, int step)
{
	if (maze[x][y] == 'E')
	{
		cout<<step<<" ";
		return true;
	}
	direct = (direct + 1) % 4;    //靠右手边走
	while(1)
	{
		int tmpx=x + dir[direct][0];
		int tmpy=y + dir[direct][1];
		if (tmpx<h&&tmpx>=0&&tmpy<w&&tmpy>=0)
		{
			if (maze[tmpx][tmpy]=='.'||maze[tmpx][tmpy]=='E')
			{
				if(rdfs(tmpx, tmpy, step + 1)) return true;
			}
		}
	direct = (direct + 3) % 4; //逆时针
	}
}
int BFS(int r,int c)
{ 
	visited[r][c] = 1;
	Node node; node.x=r; node.y=c;
	Q[0]=node;
	int first=-1,last=0;
	int cnt=0;
	while(first!=last)
	{ 
		Node v=Q[++first];
		for (int i=0;i<4;i++)
		{
			int x=v.x+dir[i][0];
			int y=v.y+dir[i][1];
			if (x<h&&x>=0&&y<w&&y>=0)
			{
				if ((maze[x][y]=='.'||maze[x][y]=='E')&&(visited[x][y]==0))
				{	
					node.x=x;node.y=y;
					Pre[x][y][0]=v.x;
					Pre[x][y][1]=v.y;
					Q[++last]=node;                     
					visited[x][y] = 1; 
				}
				if (maze[x][y]=='E')
				{
					int x0,y0;
					x0=Q[last].x;
					y0=Q[last].y;
					while (x0!=-1)
					{
						cnt++;
						int tmp=x0;
						x0=Pre[x0][y0][0];
						y0=Pre[tmp][y0][1];
					}
					return cnt;
				}
			}
		}	
	} 
}


int main()
{
	int n,i,j;
	cin>>n;
	while (n--)
	{
		cin>>w>>h;
		memset(visited,0,sizeof(visited));
		int r,c;
		for (i=0;i<h;i++)
		{
			for (j=0;j<w;j++)
			{
				cin>>maze[i][j];
				if (maze[i][j]=='S')
				{	
					r=i;c=j;
				}
			}
		}
		direct = 0; ldfs(r, c, 1);
		direct = 0; rdfs(r, c, 1);
		Pre[r][c][0]=-1;
		Pre[r][c][1]=-1;
		cout<<BFS(r,c)<<endl;
	}
	return 0;
}

    

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值