백준 16930번 (달리기, C++) / 추가 반례 [BAEKJOON]

달리기

https://www.acmicpc.net/problem/16930

시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초512 MB616689758713.454%

문제

진영이는 다이어트를 위해 N×M 크기의 체육관을 달리려고 한다.

체육관은 1×1 크기의 칸으로 나누어져 있고, 칸은 빈 칸 또는 벽이다. 

x행 y열에 있는 칸은 (x, y)로 나타낸다.

매 초마다 진영이는 위, 아래, 오른쪽, 왼쪽 중에서 이동할 방향을 하나 고르고,

그 방향으로 최소 1개, 최대 K개의 빈 칸을 이동한다.

시작점 (x1, y1)과 도착점 (x2, y2)가 주어졌을 때,

시작점에서 도착점으로 이동하는 최소 시간을 구해보자.

입력

첫째 줄에 체육관의 크기 N과 M, 1초에 이동할 수 있는 칸의 최대 개수 K가 주어진다.

둘째 줄부터 N개의 줄에는 체육관의 상태가 주어진다.

체육관의 각 칸은 빈 칸 또는 벽이고, 빈 칸은 ‘.’, 벽은 ‘#’으로 주어진다.

마지막 줄에는 네 정수 x1, y1, x2, y2가 주어진다.

두 칸은 서로 다른 칸이고, 항상 빈 칸이다.

출력

(x1, y1)에서 (x2, y2)로 이동하는 최소 시간을 출력한다.

이동할 수 없는 경우에는 -1을 출력한다.

제한

  • 2 ≤ N, M ≤ 1,000
  • 1 ≤ K ≤ 1,000
  • 1 ≤ x1, x2 ≤ N
  • 1 ≤ y1, y2 ≤ M

예제 입력 1

3 4 4
....
###.
....
1 1 3 1

예제 출력 1

3

예제 입력 2

3 4 1
....
###.
....
1 1 3 1

예제 출력 2

8

예제 입력 3

2 2 1
.#
#.
1 1 2 2

예제 출력 3

-1

출처

알고리즘 분류


추가 반례

예제 입력 A

2 2 1
..
..

0 0 0 0

예제 출력 A

0

예제 입력 B

7 4 4
....
.##.
..#.
#.#.
#...
#.##
#.##
1 1 7 2

예제 출력 B

3

예제 입력 C

7 4 4
....
.##.
.#..
.#.#
...#
##.#
##.#
1 4 7 3

예제 출력 C

3

visited 배열에 방문하는 시점을 넣고 해결하는 경우

if (_isVisted[_dx][_dy] == _cnt)
break;

위 로직으로 진행한다면 탐색하는 방향의 순서(상, 하, 좌, 우)에 따라 답이 3 ~ 4로 달라집니다.

예제 입력 D

3 3 3
..#
..#
#..
1 1 3 3

예제 출력 D

3

통과된 코드

#include <iostream>
#include <queue>
using namespace std;

int _N, _M, _K, _Temp1, _Temp2, _Res;
int _DxDy[4][2] = { { 1, 0}, { -1, 0}, { 0, 1}, { 0, -1} };
char _Map[1000][1000];
int _isVisted[1000][1000];
string _Str;
pair<int, int> _sePos[2];
queue<pair<int, pair<int, int>>> _BFSQueue;

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	cin >> _N >> _M >> _K;
	for (int i = 0; i < _N; i++) {
		cin >> _Str;
		for (int j = 0; j < _M; j++) 
			_Map[i][j] = _Str[j];
	}
	for (int i = 0; i < 2; i++) {
		cin >> _Temp1 >> _Temp2;
		_sePos[i] = make_pair(_Temp1 - 1, _Temp2 - 1);
	}

	for (int i = 0; i < _N; i++) 
		for (int j = 0; j < _M; j++)
			_isVisted[i][j] = INT32_MAX;
	
	_BFSQueue.push(make_pair(0, _sePos[0]));
	_isVisted[_sePos[0].first][_sePos[0].second] = 0;
	pair<int, int> _CntPos;
	int _dx, _dy, _cnt;
	while (!_BFSQueue.empty()) {
		_CntPos = _BFSQueue.front().second;
		_cnt = _BFSQueue.front().first;
		_BFSQueue.pop();
		if (_CntPos == _sePos[1]) {
			_Res = _cnt;
			break;
		}
		_cnt++;
		for (int i = 0; i < 4; i++) {
			for (int j = 1; j <= _K; j++) {
				_dx = _CntPos.first + _DxDy[i][0] * j;
				_dy = _CntPos.second + _DxDy[i][1] * j;
				if (_dx >= _N || _dy >= _M || _dx < 0 || _dy < 0 || _Map[_dx][_dy] == '#')
					break;
				if (_isVisted[_dx][_dy] < _cnt)
					break;
				if (_isVisted[_dx][_dy] == _cnt)
					continue;

				_BFSQueue.push(make_pair(_cnt, make_pair(_dx,_dy)));
				_isVisted[_dx][_dy] = _cnt;
			}
		}
	}

	if (_sePos[0] == _sePos[1]) cout << _Res;
	else if (_Res == 0) cout << -1;
	else cout << _Res;

	return 0;
}

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤