HDOJ 1026 Ignatius and the Princess I (深度优先搜索队列输出)

题目链接

花了一早上研究前辈的代码,才搞懂这题目。经常,做一道题目,总是要先看题解,才能做,很多时候,甚至做的时候也是照搬前辈的代码。不知道对不对,迷茫过很久,但是想想,怎么说呢,就算是抄袭别人的代码,但是自己还是学习了很多。至少你懂得了这道题目的思路了。你知道每行代码他有他自己存在的意义,不是为了美观,不是冗余而是一个独一无二的作用。所以,可能这样的方法,前进的不是那么快,那么远。可是,如今这种情况下还是蛮适合的。


~~~~~貌似扯远了,说下这道题目吧。刚开始刷OJ不久,做过DFS深度优先搜索,今天终于让我做到广度优先搜素了。不过这道题目不像前面的DFS那么简单,他多了个怪兽这东西,而且那个输出着实坑爹。


所以,必须利用队列来实现输出。


思路倒是挺简单的。具体每一步在干嘛,我写的很清楚的在代码的注释里面了。——没有注释的代码就缺少可读性,没有可读性的代码就是垃圾。


#include <iostream>
#include <memory.h>
#include <queue>
using namespace std;
char maze[101][101]; //迷宫地图
bool visited[101][101]; //BFS记录是否访问过
int n,m;
int stepx[4]={0,1,0,-1}; //stepx和stepy错开,
int stepy[4]={-1,0,1,0}; //分别为下,左,上,右
int depth; //记录走过的路长,即到达终点的时间
struct point{
	int x;
	int y;
	int hp;
	int step; //每个结点的路长
};
point path[102][102];//用来保存路长保存的是上一个到达此结点的值
queue <point> q;//广搜队列
bool isBound(point p)
{
	if(p.x<0||p.x>=n||p.y<0||p.y>=m)
	{
		return false;
	}
	return true;
}
//输出函数,其中path[x][y]中保存的是上一个到达此结点的值
void outputPath(int x,int y,int hp)
{
	if(path[x][y].x + path[x][y].y !=0) //从(0,0)开始 
		outputPath(path[x][y].x,path[x][y].y,path[x][y].hp);
	int px = path[x][y].x;
	int py = path[x][y].y;
	cout<< depth++<<"s:("<<px<<","<<py<<")->("<<x<<","<<y<<")"<<endl;
	for(int i=1;i<=hp;++i) //注意这里容易弄混,就是我们BFS里面是用maze数组的hp减少来实现的,然而我们弄了个path数组则避免hp的丢失
		cout << depth++ << "s:FIGHT AT ("<< x << "," << y << ")" << endl;
}
///广度优先搜索,查找最佳路径。这里这样处理:由于怪物的存在,破坏了广度优先搜索的结构,因此每次经过怪物时,将hp-1,再将值赋给  
///这一点,并将此点入队列,并不直接进行扩展,直到hp减为0后,将这一点设置为'.'即一般路径,进行扩展,这样能够保证同一层次找到的  
///第一个解即为最优解(因为这样处理后,所有扩展的节点代价都相等都为1) 
void BFS()
{
	bool rescue = false;
	point curr,next;
	curr.x = curr.y = curr.step = curr.hp =0; //初始化起始位置
	q.push(curr);
	visited[0][0] =  true ; // (0,0)是入口所以一直是被访问过的
	while(!q.empty())
	{
		curr = q.front();
		q.pop(); 
		//如果到达终点 则可以进行输出
		if(curr.x == n-1 && curr.y == m-1 && maze[curr.x][curr.y] == '.') //为什么不考虑最后有怪兽呢?可通过下面方法解决终点有怪兽情况
		{
			rescue = true;
			cout << "It takes " << curr.step << " seconds to reach the target position, let me show you the way." << endl;  
			depth = 1;
			outputPath(curr.x,curr.y,curr.hp);
		}
		//若碰到怪兽则将其HP--,并且将其加入队列中,这也可以解决最后有怪兽的问题。
		if(maze[curr.x][curr.y] >= '1' && maze[curr.x][curr.y]<='9')
		{
			int tmp = maze[curr.x][curr.y] - '1';
			if(tmp == 0)
				maze[curr.x][curr.y] = '.'; //如果hp减到0 则可以将其视为一个'.'
			else
				maze[curr.x][curr.y] = tmp + '0';
			curr.step ++; //一滴一滴血的打
			q.push(curr);
		}
		else //普通结点,进行扩展
		{
			//分别朝着四个方向走
			for(int i=0;i<4;i++)
			{
				next.x = curr.x + stepx[i];
				next.y = curr.y + stepy[i];
				next.step = curr.step + 1;
				//如果没访问过,不是墙壁,且不是边界则保存下来
				if(!visited[next.x][next.y]&&isBound(next)&&maze[next.x][next.y]!='X')
				{
					visited[next.x][next.y] = true;
					path[next.x][next.y].x = curr.x;
					path[next.x][next.y].y = curr.y;
					path[next.x][next.y].hp = curr.hp;

					//更新路径的血量(这样处理为了通用性,将怪兽点与路径点用同样方式处理,对怪兽点的扩展按照上面if方法)  

					if(maze[next.x][next.y] == '.')
						next.hp = 0;
					else
						next.hp = maze[next.x][next.y] - '0' ; //保存怪兽HP
					q.push(next);
				}
			}
		}
	}
	if(!rescue)
		cout << "God please help our poor hero." << endl; 
}
int main()
{
	while(cin>>n>>m)
	{
		//构造迷宫 并初始化
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<m;j++)
			{
				cin>>maze[i][j];
				visited[i][j] = false;
			}
		}
		memset(path,0,sizeof(path));
		BFS();
		cout << "FINISH" << endl; 
	}
	return 0;
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值