ZOJ 1671(广度搜索bfs)(Walking Ant)

ZOJ 1671(广度搜索bfs)


Walking Ant

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 20   Accepted Submission(s) : 15
Problem Description
Ants are quite diligent. They sometimes build their nests beneath flagstones. Here, an ant is walking in a rectangular area tiled with square flagstones, seeking the only hole leading to her nest.

The ant takes exactly one second to move from one flagstone to another. That is, if the ant is on the flagstone with coordinates (x,y) at time t, she will be on one of the five flagstones with the following coordinates at time t+1:

(x, y), (x+1, y), (x-1, y), (x, y+1), (x, y-1).

The ant cannot go out of the rectangular area. The ant can visit the same flagstone more than once.

Insects are easy to starve. The ant has to go back to her nest without starving. Physical strength of the ant is expressed by the unit "HP". Initially, the ant has the strength of 6 HP. Every second, she loses 1 HP. When the ant arrives at a flagstone with some food on it, she eats a small piece of the food there, and recovers her strength to the maximum value, i.e., 6 HP, without taking any time. The food is plenty enough, and she can eat it as many times as she wants.

When the ant's strength gets down to 0 HP, she dies and will not move anymore. If the ant's strength gets down to 0 HP at the moment she moves to a flagstone, she does not effectively reach the flagstone: even if some food is on it, she cannot eat it; even if the hole is on that stone, she has to die at the entrance of her home.

If there is a puddle on a flagstone, the ant cannot move there.

Your job is to write a program which computes the minimum possible time for the ant to reach the hole with positive strength from her start position, if ever possible.


Input

The input consists of multiple maps, each representing the size and the arrangement of the rectangular area. A map is given in the following format.

w h
d11 d12 d13 ... d1w
d21 d22 d23 ... d2w
...
dh1 dh2 dh3 ... dhw

The integers w and h are the numbers of flagstones in the x- and y-directions, respectively. w and h are less than or equal to 8. The integer dyx represents the state of the flagstone with coordinates (x, y) as follows.

0: There is a puddle on the flagstone, and the ant cannot move there.
1, 2: Nothing exists on the flagstone, and the ant can move there. `2' indicates where the ant initially stands.
3: The hole to the nest is on the flagstone.
4: Some food is on the flagstone.

There is one and only one flagstone with a hole. Not more than five flagstones have food on them.

The end of the input is indicated by a line with two zeros.

Integer numbers in an input line are separated by at least one space character.


Output

For each map in the input, your program should output one line containing one integer representing the minimum time. If the ant cannot return to her nest, your program should output -1 instead of the minimum time.


Sample Input

3 3
2 1 1
1 1 0
1 1 3
8 4
2 1 1 0 1 1 1 0
1 0 4 1 1 0 4 1
1 0 0 0 0 0 0 1
1 1 1 4 1 1 1 3
8 5
1 2 1 1 1 1 1 4
1 0 0 0 1 0 0 1
1 4 1 0 1 1 0 1
1 0 0 0 0 3 0 1
1 1 4 1 1 1 1 1
8 7
1 2 1 1 1 1 1 1
1 1 1 1 1 1 1 4
1 1 1 1 1 1 1 1
1 1 1 1 4 1 1 1
4 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 3
8 8
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 4 4 1 1 1 1 1
1 4 4 2 1 1 0 0
1 1 0 0 0 0 0 3
1 1 0 4 1 1 1 1
1 1 1 1 1 1 1 1
8 8
1 1 1 1 1 1 1 1
1 1 2 1 1 1 1 1
1 1 4 4 4 1 1 1
1 1 1 4 4 1 0 1
1 1 1 1 1 1 0 1
1 1 1 1 1 1 0 3
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
0 0


Sample Output

4
-1
13
20
-1
-1

这道题的大意是:一只蚂蚁从起点2开始向终点3走,不过这只蚂蚁有生命值(HP)初始值为6,每走一步,HP减少1,若为0,蚂蚁就死了,蚂蚁在往下一步走的时候,可以往上、下、左、右四个方向走也可以待在原地不走,但生命值HP都要减1,而且蚂蚁走过的单元格,可以再走。蚂蚁在走的过程中可能会遇到

4(食物),则蚂蚁的生命值HP补充到6(最大只能为6),但当蚂蚁在到达食物所在的单元格时,生命值为0,则蚂蚁仍然不能吃到食物。同样当蚂蚁在到达终点所在的单元格时,生命值为0,则蚂蚁仍然不能算到达终点(仍要输出-1)。(因为此时蚂蚁已经死了。)若能到达终点则输出最小步数,反之输出-1.

  思路:这题要用bfs(广度搜索)和优先队列。


注意:这题蚂蚁所走的路不能标记(其它题中标记走过的路,是为了让下次不再走(避免再走回去),从而节省时间,同时也可以避免死循环(防止一直在这个点附近徘徊)),但在该题中蚂蚁可以再走以前走过的路(当看到样例时就明白了,因为生命值有限,所以要去找食物,一来一回就走重复了,这是不能避免的),想到这,我脑子就乱了,因为不能标记,蚂蚁可以一直待在食物旁徘徊,这样程序就陷入死循环了。后来在看到高手的博客时,顿时恍然大悟:第一次碰到食物就要把食物从图中消除掉(防止死循环),因为第一次补给食物后回不了洞穴,以后再到该位置补给食物也是无济于事的。

My  soiution:

/*2015.8.6*/

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;             
int x,y,ex,ey,ans=-1,n,m,b[4]={0,1,-1,0},d[4]={1,0,0,-1};/*b[4],d[4]控制行走方向*/
int c[10][10],mark[10][10];  /*注意b[4]和d[4]内的数值之间的搭配,一次只能走一步,每次取值时*/ 
struct stu                    /*b[4]和d[4]中只能有一个取0,另一个只能取1或-1*/
{
	int x,y,t,ph;
	friend bool operator <(stu a,stu b)
	{
		return a.t>b.t;
	}
}temp,a;

int judge(int i,int j,int k)
{
	if(i<0||i>=n||j<0||j>=m||k<=0)/*这里的K值为生命值,若为0则去掉该种情况*/
	return 0;
	if(c[i][j]==0||mark[i][j]==1)/*c[i][j]==0则该点为石头,mark[i][j]==1该点被标记过不能走*/
	 return 0;
	else 
	return 1;
}
void bfs()
{
	int i;
	a.x=x;
	a.y=y;
	a.t=0;
	a.ph=6;
	priority_queue<stu>q;/*定义优先队列*/ 
	q.push(a);
	while(!q.empty())
	{
		a=q.top();
		q.pop();
		for(i=0;i<4;i++)
		{
			temp.x=a.x+b[i];
			temp.y=a.y+d[i];
			temp.t=a.t+1; /*步数加1*/ 
			temp.ph=a.ph-1;/*生命值减1*/
			if(judge(temp.x,temp.y,temp.ph))/*当执行花括号内的语句时,此时的生命值大于或等于1,满足题意*/
			{                             /*解决了生命值为0,蚂蚁却走到食物或终点处的特殊情况,因为当生命*/
				if(temp.x==ex&&temp.y==ey) /*值为0时,直接就把该点去除掉,不再判断是不是找到食物或到达终点*/
				{
					ans=temp.t;return ;/*第一次找到终点,直接结束函数调用,输出结果*/
				}
				if(c[temp.x][temp.y]==4)/*若该点为4,即食物,生命值补充满*/
				{
				   temp.ph=6;
				  mark[temp.x][temp.y]=1;/*标记该食物点*/	
				}
				
				q.push(temp);
			}
		}
		
	}
}
int main()
{
	int i,j;
	while(scanf("%d%d",&m,&n)==2&&(n||m))
	{
		ans=-1;/*刚开始忘记加了,当不能回到终点时输出的不是-1,而是上一次ans的值*/
		memset(mark,0,sizeof(mark));/*初始化标记数组*/
		for(i=0;i<n;i++)
		{
			for(j=0;j<m;j++)
			{
				scanf("%d",&c[i][j]);
				if(c[i][j]==2)
				{
					x=i;y=j;
				}
				if(c[i][j]==3)
				{
					ex=i;ey=j;
				}
			}	
		}
		bfs();
		if(ans!=-1)
		printf("%d\n",ans);
		else
		printf("%d\n",ans);	
	}	
	return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值