torus711 のアレ

主に競技プログラミングの問題について書きます

Codeforces #149, Division 2, C : King's Path

概要

10^{10}×10^{10} のチェス盤にキングが置かれている。
キングを ( x0, y0 ) から ( x1, y1 ) まで移動させたい。
使用可能なセルの情報が与えられるので、最小の移動回数を出力せよ。
移動できない場合は -1 を出力せよ。

解法

実は制約がゆるい。
> It is guaranteed that the total length of all given segments doesn't exceed 10^5.
なので、適当に BFS すれば通る。

本番で書いたコード

typedef pair< PII, int > State;

int solve( set< PII > cells, int x0, int y0, int x1, int y1 )
{
	queue< State > que;
	que.push( MP( MP( x0, y0 ), 0 ) );

	map< PII, int > visited;
	visited[ MP( x0, y0 ) ] = 0;

	while ( !que.empty() )
	{
		auto cur = que.front().fst;
		auto turn = que.front().snd;
		que.pop();


		if ( cur == MP( x1, y1 ) )
		{
			return turn;
		}

		REP( i, -1, 2 )
		{
			REP( j, -1, 2 )
			{
				auto next = cur;

				next.fst += i;
				next.snd += j;

				if ( !EXIST( cells, next ) || EXIST( visited, next ) && visited[ next ] <= turn + 1 )
				{
					continue;
				}

				que.push( MP( next, turn + 1 ) );
				visited[ next ] = turn + 1;
			}
		}
	}

	return -1;
}

int main()
{
	cin.tie( 0 );
	ios::sync_with_stdio( false );

	int x0, y0, x1, y1;
	cin >> x0 >> y0 >> x1 >> y1;

	int n;
	cin >> n;

	set< PII > cells;

	REP( i, 0, n )
	{
		int r, a, b;
		cin >> r >> a >> b;

		REP( i, a, b + 1 )
		{
			cells.insert( MP( r, i ) );
		}
	}

	cout << solve( cells, x0, y0, x1, y1 ) << endl;

	return 0;
}