hdu 1026 Ignatius and the Princess I(bfs)

Ignatius and the Princess I

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 16269    Accepted Submission(s): 5164

Special Judge

Problem Description

The Princess has been abducted by the BEelzebub feng5166, our hero Ignatius has to rescue our pretty Princess. Now he gets into feng5166‘s castle. The castle is a large labyrinth. To make the problem simply, we assume the labyrinth is a N*M two-dimensional
array which left-top corner is (0,0) and right-bottom corner is (N-1,M-1). Ignatius enters at (0,0), and the door to feng5166‘s room is at (N-1,M-1), that is our target. There are some monsters in the castle, if Ignatius meet them, he has to kill them. Here
is some rules:

1.Ignatius can only move in four directions(up, down, left, right), one step per second. A step is defined as follow: if current position is (x,y), after a step, Ignatius can only stand on (x-1,y), (x+1,y), (x,y-1) or (x,y+1).

2.The array is marked with some characters and numbers. We define them like this:

. : The place where Ignatius can walk on.

X : The place is a trap, Ignatius should not walk on it.

n : Here is a monster with n HP(1<=n<=9), if Ignatius walk on it, it takes him n seconds to kill the monster.

Your task is to give out the path which costs minimum seconds for Ignatius to reach target position. You may assume that the start position and the target position will never be a trap, and there will never be a monster at the start position.

Input

The input contains several test cases. Each test case starts with a line contains two numbers N and M(2<=N<=100,2<=M<=100) which indicate the size of the labyrinth. Then a N*M two-dimensional array follows, which describe the whole labyrinth. The input is terminated
by the end of file. More details in the Sample Input.

Output

For each test case, you should output "God please help our poor hero." if Ignatius can‘t reach the target position, or you should output "It takes n seconds to reach the target position, let me show you the way."(n is the minimum seconds), and tell our hero
the whole path. Output a line contains "FINISH" after each test case. If there are more than one path, any one is OK in this problem. More details in the Sample Output.

Sample Input

5 6
.XX.1.
..X.2.
2...X.
...XX.
XXXXX.
5 6
.XX.1.
..X.2.
2...X.
...XX.
XXXXX1
5 6
.XX...
..XX1.
2...X.
...XX.
XXXXX.

Sample Output

It takes 13 seconds to reach the target position, let me show you the way.
1s:(0,0)->(1,0)
2s:(1,0)->(1,1)
3s:(1,1)->(2,1)
4s:(2,1)->(2,2)
5s:(2,2)->(2,3)
6s:(2,3)->(1,3)
7s:(1,3)->(1,4)
8s:FIGHT AT (1,4)
9s:FIGHT AT (1,4)
10s:(1,4)->(1,5)
11s:(1,5)->(2,5)
12s:(2,5)->(3,5)
13s:(3,5)->(4,5)
FINISH
It takes 14 seconds to reach the target position, let me show you the way.
1s:(0,0)->(1,0)
2s:(1,0)->(1,1)
3s:(1,1)->(2,1)
4s:(2,1)->(2,2)
5s:(2,2)->(2,3)
6s:(2,3)->(1,3)
7s:(1,3)->(1,4)
8s:FIGHT AT (1,4)
9s:FIGHT AT (1,4)
10s:(1,4)->(1,5)
11s:(1,5)->(2,5)
12s:(2,5)->(3,5)
13s:(3,5)->(4,5)
14s:FIGHT AT (4,5)
FINISH
God please help our poor hero.
FINISH

题意:从(0,0)到(n-1,m-1)‘.‘代表路,‘X‘代表障碍,‘n’带表怪物血量,打过就可以过了,消耗时间n

题目思想:

广搜(bfs)

这是我第一次接触到广搜,就大致查询了一下广搜,再结合以前的深搜,总结如下:

深搜是与栈有关:

拿树来做例子,深搜是把树的某个分支进行到底再查找另一个分支,直到满足条件结束或者分支找完结束

再说说与栈的关系:栈,先进后出,即把树的根放在栈底上面的栈内元素就可以依次换元,就可以遍历完整个结构

再说说在图中:即从起始点走到终点再返回一步再往下走,直到满足条件或者遍历完成

广搜是与队有关:

拿树来做例子,广搜一层一层地遍历,就像树一样,一层一层展开的枝繁叶茂

再说说与队列的关系:队列是先进先出,即我们拿到一个节点可以把他所有的子节点全部进队,而总是把一层的节点遍历完成才会进行到下一层

再说说在图中:从起点开始一层一层向外延伸(类似于一个墨滴在纸上扩散的视觉效果),直到满足条件或者遍历完成

AC代码:

#include<iostream>
#include<queue>
#include<stack>
#include<stdlib.h>
#include<iomanip>
using namespace std;

int n,m;
char map[101][101];

typedef struct point
{
	int x,y,step,time;//step用于记录到此点的方向,step=1,2,3,4 ->上下左右
}*prt;//因为队中元素需要修改,用指针
prt t[100][100];

bool cheak(int x,int y)//判断是否可达
{
	if(x<0||y<0||x>=n||y>=m||map[x][y]=='X')
		return false;
	return true;
}
//广搜遍历所有可能
void bfs()
{
	queue<prt> Q;//因为队中元素需要修改,用指针
	prt corrent;
	int x,y,k,i;
	bool flag;
	t[0][0]->time=0;//出发点时间置0
	Q.push(t[0][0]);//出发点进队
	while(!Q.empty())
	{
		corrent=Q.front();
		x=corrent->x;
		y=corrent->y;
		Q.pop();
		//对于上下左右四个点进行查看:
		//	如果可以达到,并且从当前点走过去比以前方式到达他的时间小
		//	就将这个点进队
		//	这里既有初始情况到达,也有事后修改,并且修改需要修改以后所有点,所以也需要进队(即最后样例所给)
		if(cheak(x-1,y)&&corrent->time+map[x-1][y]-'0'+1<t[x-1][y]->time)
		{
				t[x-1][y]->time=corrent->time+map[x-1][y]-'0'+1;
				Q.push(t[x-1][y]);
				t[x-1][y]->step=4;
		}
		if(cheak(x+1,y)&&corrent->time+map[x+1][y]-'0'+1<t[x+1][y]->time)
		{
				t[x+1][y]->time=corrent->time+map[x+1][y]-'0'+1;
				Q.push(t[x+1][y]);
				t[x+1][y]->step=3;
		}
		if(cheak(x,y-1)&&corrent->time+map[x][y-1]-'0'+1<t[x][y-1]->time)
		{
				t[x][y-1]->time=corrent->time+map[x][y-1]-'0'+1;
				Q.push(t[x][y-1]);
				t[x][y-1]->step=2;
		}
		if(cheak(x,y+1)&&corrent->time+map[x][y+1]-'0'+1<t[x][y+1]->time)
		{
				t[x][y+1]->time=corrent->time+map[x][y+1]-'0'+1;
				Q.push(t[x][y+1]);
				t[x][y+1]->step=1;
		}
	}
}

int main()
{
	int k,i,order,time;
	while(cin>>n>>m)
	{
		for(k=0;k<n;k++)
			for(i=0;i<m;i++)
			{
				t[k][i]=new point;
				cin>>map[k][i];
				if(map[k][i]=='.')
					map[k][i]='0';
				t[k][i]->x=k;
				t[k][i]->y=i;
				t[k][i]->time=10000000;
				t[k][i]->step=-1;
			}
		t[0][0]->step=1;
		bfs();

		if(t[n-1][m-1]->time<10000000)//如果可以到达目的地
		{
			cout<<"It takes "<<t[n-1][m-1]->time<<" seconds to reach the target position, let me show you the way."<<endl;
			stack<point> S;
			point p,last;
			k=n-1;
			i=m-1;
			while(k>=0&&i>=0)//由最后点按照每一点的step找到路线 ,找到的上一点都入栈
			{
				p.x=k;
				p.y=i;
				S.push(p);
				order=t[k][i]->step;
				if(order==4)
					k+=1;
				if(order==3)
					k-=1;
				if(order==2)
					i+=1;
				if(order==1)
					i-=1;
			}
			p=S.top();
			S.pop();
			time=1;
			while(!S.empty())//输出栈
			{
				last=p;
				p=S.top();
				cout<<(time++)<<"s:("<<last.x<<","<<last.y<<")->("<<p.x<<","<<p.y<<")"<<endl;
				for(k=0;k<map[p.x][p.y]-'0';k++)//输出在某点打怪消耗时间
					cout<<(time++)<<"s:FIGHT AT ("<<p.x<<","<<p.y<<")"<<endl;
				S.pop();
			}
		}
		else
			cout<<"God please help our poor hero."<<endl;

		cout<<"FINISH"<<endl;

		for(k=0;k<n;k++)//删除申请空间
			for(i=0;i<m;i++)
				delete t[k][i];
	}
	return 0;
}

测试样例:

5 6

.XX.1.

..X.9.

2...X.

...XX.

XXXXX.

时间: 2024-11-05 20:33:23

hdu 1026 Ignatius and the Princess I(bfs)的相关文章

HDU 1026 Ignatius and the Princess I (BFS)

题目链接 题意 : 从(0,0)点走到(N-1,M-1)点,问最少时间. 思路 : BFS..... 1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 #include <iostream> 5 6 using namespace std ; 7 8 struct node 9 { 10 int x,y ; 11 int tim ; 12 friend bool operator

hdu 1026 Ignatius and the Princess I (BFS+优先队列)

Ignatius and the Princess I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 11700    Accepted Submission(s): 3653Special Judge Problem Description The Princess has been abducted by the BEelzebub

HDU 1026 Ignatius and the Princess I(bfs +记录路径)

Ignatius and the Princess I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 14184    Accepted Submission(s): 4474 Special Judge Problem Description The Princess has been abducted by the BEelzeb

HDU 1026 Ignatius and the Princess I (基本算法-BFS)

Ignatius and the Princess I Problem Description The Princess has been abducted by the BEelzebub feng5166, our hero Ignatius has to rescue our pretty Princess. Now he gets into feng5166's castle. The castle is a large labyrinth. To make the problem si

hdu 1028 Ignatius and the Princess III(母函数)

题意: N=a[1]+a[2]+a[3]+...+a[m];  a[i]>0,1<=m<=N; 例如: 4 = 4;  4 = 3 + 1;  4 = 2 + 2;  4 = 2 + 1 + 1;  4 = 1 + 1 + 1 + 1; 共有5种. 给N,问共有几种构造方式. 思路: 一个数N分解的式子中1的个数可以是0,1,2,3,...,N. 2的个数可以是0,1,2,...,N/2. .... 母函数基础题,, 看代码. 当然也可以用DP(背包) 母函数代码: int N,num;

HDU 1026 Ignatius and the Princess I(优先队列+打印路径)

题意:n*m的迷宫,从(0,0)到(n-1,m-1),遇到怪物停留怪物所在方格中的数字个单位时间,求最短时间并打印路径: 思路:用bfs先搜最短路,搜最短路时一定要用优先队列,不然结果不对:在通过保存上一步的方法保存路径,到达终点时,将路径查询出来,遇到怪物是位置不变: #include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std; int

hdu 1026 Ignatius and the Princess I(优先队列+bfs+记录路径)

以前写的题了,现在想整理一下,就挂出来了. 题意比较明确,给一张n*m的地图,从左上角(0, 0)走到右下角(n-1, m-1). 'X'为墙,'.'为路,数字为怪物.墙不能走,路花1s经过,怪物需要花费1s+数字大小的时间. 比较麻烦的是需要记录路径.还要记录是在走路还是在打怪. 因为求最短路,所以可以使用bfs. 因为进过每一个点花费时间不同,所以可以使用优先队列. 因为需要记录路径,所以需要开一个数组,来记录经过节点的父节点.当然,记录方法不止一种. 上代码—— 1 #include <c

hdu 1029 Ignatius and the Princess IV(排序)

题意:求出现次数>=(N+1)/2的数 思路:排序后,输出第(N+1)/2个数 #include<iostream> #include<stdio.h> #include<algorithm> using namespace std; int a[999999]; int main(){ int n,i; while(~scanf("%d",&n)){ for(i=0;i<n;++i) scanf("%d",&

hdu 1028 Ignatius and the Princess III(母函数,完全背包)

http://acm.hdu.edu.cn/showproblem.php?pid=1028 整数划分问题. 第一道母函数...母函数入门 小于等于n的整数共有n个,1,2......n,每个数都有无限多个,对于整数1,它所对应的母函数为(1+x+x^2+...+x^k+...),整数2对应的母函数为(1+x^2+X^4+...+x^(2*k)+...),整数3对应的母函数为(1+x^3+x^6+...+x^(3*k)+...),以此类推,直到整数n. 那么n的整数划分的个数就是这n个母函数乘积