题目描述:点击打开链接
题意是在某一时刻t会有一个陨石落下来,会落到坐标为x,y的地方,陨石落下来之后不但x,y会遭到破坏,和x,y四邻接的点也会被破坏。现在Bessie的初始位置在原点,每一个单位时间只能平行于坐标轴,移动一个单位距离,题目要求需要几个单位时间Bessie才能移动到安全的地方(只能运动在坐标轴和第一象限)。由于陨石落下来之前,某个点还是可以走的,直到t时刻陨石落下来破坏掉该点。
明确题意后首先想到的是BFS,预处理是这题的难点,由于某个点遭到破坏后就不能走了,因此如果有多次遭破坏只要记录改点遭破坏的最早的时间就可以了。bfs的时候如果移动步数大于等于该点被破坏的时间,那么该节点就不能被扩展。直到走到不会被陨石破坏的点为止。
代码如下:
数组mp记录了每个点被陨石破坏的最早时间,如果不会被破坏则用-1表示(由于题目中t可以是0,因此不能用0表示不会被破坏,在这里wa了一次)
#include <iostream>
#include <algorithm>
#include <string>
#include <queue>
using namespace std;
int mp[309][309];
int dir[4][2] = {{1,0}, {-1,0}, {0,-1}, {0,1}};
int visit[309][309];
struct State
{
int x, y, step;
State(int x, int y, int step) : x(x), y(y), step(step) {}
};
bool inFirstQuadrant( int x, int y )
{
if ( x >= 0 && y >= 0 ) return true;
return false;
}
void setPoint(int x, int y, int t)
{
if ( mp[x][y] == -1 ) mp[x][y] = t;
else mp[x][y] = min(mp[x][y], t);
}
void destroyPoint( int x, int y, int t )
{
setPoint(x, y, t);
for ( int i=0; i<4; i++ )
{
int tx = x + dir[i][0];
int ty = y + dir[i][1];
if ( inFirstQuadrant( tx, ty ) )
setPoint( tx, ty, t );
}
}
void BFS()
{
State origin( 0, 0, 0 );
queue<State> Q;
Q.push( origin );
visit[0][0] = 1;
while( ! Q.empty() )
{
State cur = Q.front();
Q.pop();
if ( mp[cur.x][cur.y] == -1 )
{
cout << cur.step << endl;
return;
}
for ( int i=0; i<4; i++ )
{
int x = cur.x + dir[i][0];
int y = cur.y + dir[i][1];
if ( inFirstQuadrant(x, y) && !visit[x][y])
{
if ( cur.step + 1 < mp[x][y] || mp[x][y] == -1)
{
State p( x, y, cur.step + 1 );
Q.push( p );
visit[x][y] = 1;
}
}
}
}
cout << -1 << endl;
}
int main()
{
int m;
while ( cin >> m )
{
memset( mp, -1, sizeof(mp) );
memset( visit, 0, sizeof(visit) );
int x, y, t;
for ( int i=0; i<m; i++ )
{
cin >> x >> y >> t;
destroyPoint( x, y, t );
}
BFS();
}
return 0;
}