炸弹问题,题中加了一个小人拿到i个炸弹后去炸墙,一个炸弹能炸一面墙
一步所需时间为1秒,安炸弹到爆炸所需要一秒,也就是说从走到那面墙开始算起到通过那面墙所需要的时间为2秒
问多少秒后可以到达出口
如果出不去就输出-1
记录S点的坐标后开始BFS
由于有炸错墙的可能性,所以炸了墙之后不能在原图map中修改,需要有一个记录状态的数组 这里叫做state 在结构体里
state[i][j]表示在走到(i,j)的时候的炸弹数
一开始没走的时候初始化为-1吧是为了不跟没有炸弹时候的0混淆
遇到炸弹拿炸弹 遇到墙炸了它 如果是平路的话就要实时更新身上携带的炸弹数
然后用本次路径结束后所剩余的炸弹数跟上次路径结束后的炸弹数相比
如果比上次路径结束后的炸弹多的话就入队 意味着少用了炸弹也就是时间少了还有就是不需要炸那么多墙
然后实时更新本次状态
最重要是更新本次在(x1,y1)点时候身上的炸弹
然后就是判断哪条路径走的秒数少啦 在状态判断的时候其实也有一部分原因是为了判断最短路径
思路很清晰接下来贴代码 代码也有一部分注释
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cctype>
#include<algorithm>
#include<cmath>
#define INF 100000
using namespace std;
int N, M, ans, sx, sy;
char map[10][10];
int dir[4][2] = { 0, 1, 0, -1, 1, 0, -1, 0 };
struct Node
{
int x, y, vs, step;
int state[8][8];
int check( int x, int y )
{
if( x >= 0 && x < N && y >= 0 && y < M )
return 1;
return 0;
}
} now;
int BFS( )
{
memset( now.state, -1, sizeof( now.state ) ) ; //初始化状态到达每个点的炸弹为-1(为了和到达某个点时炸弹为0混淆)
now.x = sx;
now.y = sy;
now.step= 0;
now.vs = 0;//身上拥有的炸弹初始化为0
now.state[sx][sy] = 0;//起点炸弹数为0
queue<Node>q;
q.push(now);
while( !q.empty() )
{
Node temp = q.front();
q.pop();
if( ans != INF && temp.step >= ans )
continue;
for( int i = 0; i < 4; ++i )
{
int x1 = temp.x + dir[i][0];
int y1 = temp.y + dir[i][1];
int t1 = temp.step;
int vs1 = -1;
if(now.check(x1,y1))
{
if( map[x1][y1] == 'D' )//找到终点
{
ans = min(ans,t1+1);//寻找最优路线(步数最少)
continue;
}
else if( temp.state[x1][y1] > -1 || map[x1][y1] == '.' ) // 该点已经走过
{
t1 += 1;
vs1 = temp.vs;//实时更新身上携带的炸弹数
}
else if( map[x1][y1] == 'X' && temp.vs > 0 )//遇到墙而且身上有炸弹
{
t1 += 2;//走上前引爆墙总共需要2秒
vs1 = temp.vs - 1;//引爆一个炸弹
}
else if( isdigit( map[x1][y1] ) )//遇到炸弹
{
t1 += 1;//走一步拿炸弹
vs1 = temp.vs + ( map[x1][y1] - '0' );//拿炸弹
}
if( vs1 > temp.state[x1][y1] )//本次携带的炸弹数量多于上次在(x1,y1)坐标时的炸弹数量
{
now.x = x1, now.y = y1, now.step = t1;
now.vs = vs1;
memcpy( now.state, temp.state, sizeof( now.state ) );//状态更新
now.state[x1][y1] = vs1;
q.push(now);//now 为最优 入队
}
}
}
}
if( ans == INF )
return 0;
else
return 1;
}
int main()
{
while( scanf( "%d %d", &N, &M ), N | M )
{
for( int i = 0; i < N; ++i )
{
scanf( "%s", map[i] );
for( int j = 0; j < M; ++j )
{
if( map[i][j] == 'S' )
sx = i, sy = j;
}
}
ans = INF;
if(BFS())
{
printf("%d\n",ans);
}
else printf("-1\n");
// printf( BFS() ? "%d\n" : "-1\n", ans );
}
return 0;
}