PKU 3669 Meteor Shower(BFS)

題目描述:點擊打開鏈接

        題意是在某一時刻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;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章