HDU-2128 Tempter of the Bone II BFS

Tempter of the Bone II

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 98304/32768 K (Java/Others)
Total Submission(s): 704    Accepted Submission(s): 160


Problem Description
The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it up, the maze was changed and the way he came in was lost.He realized that the bone was a trap, and he tried desperately to get out of this maze.


The maze was a rectangle with the sizes of N by M. The maze is made up of a door,many walls and many explosives. Doggie need to reach the door to escape from the tempter. In every second, he could move one block to one of the upper, lower, left or right neighboring blocks. And if the destination is a wall, Doggie need another second explode and a explosive to explode it if he had some explosives. Once he entered a block with explosives,he can take away all of the explosives. Can the poor doggie survive? Please help him.
 


Input
The input consists of multiple test cases. The first line of each test case contains two integers N, M,(2 <= N, M <= 8). which denote the sizes of the maze.The next N lines give the maze layout, with each line containing M characters. A character is one of the following:

'X': a block of wall;  
'S': the start point of the doggie;  
'D': the Door;
'.': an empty block;
'1'--'9':explosives in that block.

Note,initially he had no explosives.

The input is terminated with two 0's. This test case is not to be processed.
 


Output
For each test case, print the minimum time the doggie need to escape if the doggie can survive, or -1 otherwise.
 


Sample Input
4 4 SX.. XX.. .... 1..D 4 4 S.X1 .... ..XX ..XD
 


Sample Output
-1 9
 


      比较恶心的一道BFS题目,题中所设定的规则无法进行很好的抽象,网上参考了他人的思路后才发现大家的写法都算是比较蛮力的。因为这题的题目要求是小人能否走出迷宫,在迷宫中,小主人公能够拿炸弹去炸墙是令人极其蛋疼的,无论如何,这将使得这一炸极富艺术感,可能炸对,亦可能炸错,(程序无法事先知道是是否该炸)而错误的投掷炸弹又会损耗弹药,因此,原图的保留至关重要,不能因为炸弹把墙炸了就在原图上动刀子。原因是你可能炸错了墙。所以这里在每一步中的节点中保留整个图各点的炸药数,复杂的规则致使这一处理变得必需。像一般的BFS一样,同样有如队要求,不过这题比较隐晦,入队的要求是该次身上所有炸弹比上次在该点的炸弹数多。然后就是判定上的一点小技巧,如果某点是墙的话,直接将其炸药数统计好,判定一个点是否可走就只要看该条路径中是否走过改点,后面才判定是否为墙,这样就可以在满足不拆墙的情况下,通过该地方。

  代码如下:

  1 #include <cstring>
2 #include <cstdlib>
3 #include <cstdio>
4 #include <queue>
5 #include <cctype>
6 #define INF 100000
7 using namespace std;
8
9 int N, M, ans, sx, sy;
10
11 char map[10][10];
12
13 int dir[4][2] = { 0, 1, 0, -1, 1, 0, -1, 0 };
14
15 struct Node
16 {
17 int x, y, vs, step;
18 int mvs[8][8];
19 bool logic( int tx, int ty )
20 {
21 if( tx >= 0 && tx < N && ty >= 0 && ty < M )
22 return true;
23 return false;
24 }
25 bool operator < ( Node t ) const
26 {
27 return step < t.step;
28 }
29 } info;
30
31
32 bool BFS( )
33 {
34 info.x = sx, info.y = sy;
35 info.step= 0, info.vs = 0;
36 memset( info.mvs, -1, sizeof( info.mvs ) ); // 初始化为-1
37 info.mvs[sx][sy] = 0;
38 queue<Node>q;
39 q.push( info );
40 while( !q.empty() )
41 {
42 Node pos = q.front();
43 q.pop();
44 if( ans != INF && pos.step >= ans )
45 continue;
46 for( int i = 0; i < 4; ++i )
47 {
48 int tx = pos.x + dir[i][0], ty = pos.y + dir[i][1];
49 int tt = pos.step, tvs = -1;
50 if( info.logic( tx, ty ) )
51 {
52 if( map[tx][ty] == 'D' )
53 {
54 ans = ans < tt + 1 ? ans : tt + 1;
55 continue;
56 }
57 else if( pos.mvs[tx][ty] > -1 || map[tx][ty] == '.' ) // 该点已经走过
58 tt += 1, tvs = pos.vs;
59 else if( map[tx][ty] == 'X' && pos.vs > 0 )
60 {
61 tt += 2;
62 tvs = pos.vs - 1;
63 }
64 else if( isdigit( map[tx][ty] ) )
65 {
66 tt += 1;
67 tvs = pos.vs + ( map[tx][ty] - '0' );
68 }
69 if( tvs > pos.mvs[tx][ty] )
70 {
71 info.x = tx, info.y = ty, info.step = tt;
72 info.vs = tvs;
73 memcpy( info.mvs, pos.mvs, sizeof( info.mvs ) );
74 info.mvs[tx][ty] = tvs;
75 q.push( info );
76 }
77 }
78 }
79 }
80 if( ans == INF )
81 return false;
82 else
83 return true;
84 }
85
86
87 int main()
88 {
89 while( scanf( "%d %d", &N, &M ), N | M )
90 {
91 for( int i = 0; i < N; ++i )
92 {
93 scanf( "%s", map[i] );
94 for( int j = 0; j < M; ++j )
95 {
96 if( map[i][j] == 'S' )
97 sx = i, sy = j;
98 }
99 }
100 ans = INF;
101 printf( BFS() ? "%d\n" : "-1\n" , ans );
102
103 }
104 return 0;
105 }

你可能感兴趣的:(HDU)