1671 Walking Ant【bfs】

来源:互联网 发布:free mobile java韩国 编辑:程序博客网 时间:2024/04/29 01:30

ZOJ Problem Set - 1671
Walking Ant

Time Limit: 2 Seconds      Memory Limit: 65536 KB

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


这个题的题意是一只蚂蚁想回到自己的家里(3 表示),0 代表不能走的地方,4 代表食物(经过这里会恢复满血),0 是空地,2 是他当前位置,规定,蚂蚁满血有 6 点,没走一步耗费一点hp,任何时候都不能低于 1 点hp,不管是回到家了,或者见到食物了,给出现在蚂蚁周围的地图,求蚂蚁能否到达自己的家里,如果能,求出最少需要多少时间.....

求最优解,bfs 题目,

这个题比较巧妙的地方是,一般的bfs,在走过某个点之后把这个点标记上,然后下次不用考虑这个状态了,但是这个题,蚂蚁可以重复走某条路,因为路上某个地方可能有食物,重复走一遍,自身的状态可能比上一次经过这个点之后的状态更优--这也就是为什么平时的bfs 都要标记状态,因为一般的情况下,先出现的状态会比后来某一次再次出现这种状态更优(bfs解决的就是最优解问题),但是这个问题变了,中间过程会导致后出现的这个状态不一定比前上一次某个时间的状态更优,因为蚂蚁的 hp 会变动,为了解决这个问题,需要一个三维数组,同时来标记蚂蚁的位置和自身状态(一般情况只标记位置),这样的话,把三种状态全部统计下来,就不会出现某种状态没有考虑到的状态,另外加上条件的控制,正规的bfs处理方法,就可以很好的处理这个问题了.


#include<stdio.h>#include<string.h>#include<queue>using namespace std;int x[20][20],v[20][20][20],l,w;int fx[4]={-1,0,0,1},fy[4]={0,-1,1,0};struct ant{int x,y,h,t;}site,temp;queue<ant> q;void bfs(){while(!q.empty()){site=q.front();q.pop();if(x[site.x][site.y]==3)//到家了 {return;}if(site.h<2)//下一步绝对活不了...{continue;}for(int i=0;i<4;++i)//开始向四个方向前进 {int tx=site.x+fx[i],ty=site.y+fy[i];//走向的位置 if(tx<1||tx>l||ty<1||ty>w||x[tx][ty]==0) {continue;//越界或者水池,体力为0  }int th=site.h-1;//往哪走都要费一格血temp.h=th;//记录现在的可以入队的状态if(x[tx][ty]==4)//如果下一步开饭了 {th=temp.h=6;//满血复活 }if(!v[tx][ty][th])//这种状态未出现过 {temp.x=tx;temp.y=ty;temp.t=site.t+1;q.push(temp);v[tx][ty][th]=1;//标记 }}}site.t=-1;//如果队列空了还没找到,那么就不能回到家了....}int main(){int i,j,a,b,s;while(scanf("%d%d",&w,&l),l|w){for(i=1;i<=l;++i){for(j=1;j<=w;++j){scanf("%d",&s);x[i][j]=s;if(s==2)//找到现在位置{a=i;b=j;}}}while(!q.empty()){q.pop();}memset(v,0,sizeof(v));site.x=a;site.y=b;site.h=6;site.t=0;//初始状态入队 v[a][b][6]=1;q.push(site);bfs();printf("%d\n",site.t);}return 0;} 





0 0
原创粉丝点击