杭电OJ 1072图搜 Nightmare(bfs)(图搜)

Nightmare

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 8949    Accepted Submission(s): 4297


Problem Description
Ignatius had a nightmare last night. He found himself in a labyrinth with a time bomb on him. The labyrinth has an exit, Ignatius should get out of the labyrinth before the bomb explodes. The initial exploding time of the bomb is set to 6 minutes. To prevent the bomb from exploding by shake, Ignatius had to move slowly, that is to move from one area to the nearest area(that is, if Ignatius stands on (x,y) now, he could only on (x+1,y), (x-1,y), (x,y+1), or (x,y-1) in the next minute) takes him 1 minute. Some area in the labyrinth contains a Bomb-Reset-Equipment. They could reset the exploding time to 6 minutes.

Given the layout of the labyrinth and Ignatius' start position, please tell Ignatius whether he could get out of the labyrinth, if he could, output the minimum time that he has to use to find the exit of the labyrinth, else output -1.

Here are some rules:
1. We can assume the labyrinth is a 2 array.
2. Each minute, Ignatius could only get to one of the nearest area, and he should not walk out of the border, of course he could not walk on a wall, too.
3. If Ignatius get to the exit when the exploding time turns to 0, he can't get out of the labyrinth.
4. If Ignatius get to the area which contains Bomb-Rest-Equipment when the exploding time turns to 0, he can't use the equipment to reset the bomb.
5. A Bomb-Reset-Equipment can be used as many times as you wish, if it is needed, Ignatius can get to any areas in the labyrinth as many times as you wish.
6. The time to reset the exploding time can be ignore, in other words, if Ignatius get to an area which contain Bomb-Rest-Equipment, and the exploding time is larger than 0, the exploding time would be reset to 6.
 

Input
The input contains several test cases. The first line of the input is a single integer T which is the number of test cases. T test cases follow.
Each test case starts with two integers N and M(1<=N,Mm=8) which indicate the size of the labyrinth. Then N lines follow, each line contains M integers. The array indicates the layout of the labyrinth.
There are five integers which indicate the different type of area in the labyrinth:
0: The area is a wall, Ignatius should not walk on it.
1: The area contains nothing, Ignatius can walk on it.
2: Ignatius' start position, Ignatius starts his escape from this position.
3: The exit of the labyrinth, Ignatius' target position.
4: The area contains a Bomb-Reset-Equipment, Ignatius can delay the exploding time by walking to these areas.
 

Output
For each test case, if Ignatius can get out of the labyrinth, you should output the minimum time he needs, else you should just output -1.
 

Sample Input
 
   
3 3 3 2 1 1 1 1 0 1 1 3 4 8 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 5 8 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
 

Sample Output
 
   
4 -1 13
 

Author
Ignatius.L

难度并不是特别大的一道图搜题,不知道深搜结果什么样,没有尝试,这里详解我的广搜代码:

题目大意:有这么个图,有这个么主人公在2号作为起点,想要走到终点3.图中1为可走道路,0为不能走的道路,4是增加boom时间的点。初始主人公身上有个时间为6的炸弹。走一步时间-1,如果变成了0,即使走到了终点3或者是使炸弹时间初始化的4,也算是死亡了。

规则很容易理解,但是题目中一句:如果你需要,可以重复到4这个点补充炸弹时间。最初是让我犯糊涂的一个点,其实广搜的题目中有类似的很多这样的题目,我们用一个贪心思想来解答这个困难点:如果我回头了,步数就多了,而且如果从当前补充点继续走,走不到终点或者是下一个补充点,我们无论多少次补充时间都是徒劳,该走不出去还是走不出去,所以我们设置这个点只能走一次。如果走过了,图改4为0。

第一个难点我们用贪心的思想来解决了,然后我们还有一个困难点如题中样例输入3:

5 8

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


这里我们很容易看出来,从2起点开始出发,我们只能向左走,向右走是走不到终点的。然后向左下走的时候,我们需要进入4然后再出4,这个时候我们就涉及到一个重复走点的问题。通常情况下,入门的搜索题中我们设置的二维数组vis[][]用来标记这个点是否走过。用0/1来表示是否走过,以避免走回头路(多余).而且很可能进入死循环。但是这里如果这样标记的话 我们走到左边第一个4的时候,我们就出不去了,这里我们要解决重路的问题。

这个题,涉及到的变量并不多,无非x,y(坐标)step(步数).time(主角身上boom的剩余时间.)我们想再x.y上边做文章是很不容易的。在step上做标记也是很难实现的.这个时候我们还是直接想到了再boom的剩余时间上做文章,我们可以标记走到这步的时候boom的剩余时间是多少.如果走到这步的时候的boom剩余时间和上次标记的boom剩余时间不一样,那就说明我得到了补充。然而我们另开数组是不合算的,我们直接在vis数组上做文章就可以了:

#include
#include
#include
using namespace std;
struct zuobiao
{
    int x,y,time;
}now,nex;
int fx[4]={0,0,-1,1};
int fy[4]={1,-1,0,0};
int a[120][120];
int vis[120][120];
int output[120][120];
int n,m;
void bfs(int x,int y)
{
    queues;
    memset(vis,0,sizeof(vis));
    memset(output,0,sizeof(output));
    vis[x][y]=6;
    now.x=x;
    now.y=y;
    now.time=6;
    s.push(now);
    while(!s.empty())
    {
        now=s.front();
        s.pop();
        for(int i=0;i<4;i++)
        {
            nex.x=now.x+fx[i];
            nex.y=now.y+fy[i];
            nex.time=now.time;
            if(nex.x>=0&&nex.x=0&&nex.y




















你可能感兴趣的:(搜索)