백준 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

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
3 4 4
....
###.
....
1 1 3 1
3 4 4 .... ###. .... 1 1 3 1
3 4 4
....
###.
....
1 1 3 1

예제 출력 1

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
3
3
3

예제 입력 2

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
3 4 1
....
###.
....
1 1 3 1
3 4 1 .... ###. .... 1 1 3 1
3 4 1
....
###.
....
1 1 3 1

예제 출력 2

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
8
8
8

예제 입력 3

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
2 2 1
.#
#.
1 1 2 2
2 2 1 .# #. 1 1 2 2
2 2 1
.#
#.
1 1 2 2

예제 출력 3

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
-1
-1
-1

출처

알고리즘 분류


추가 반례

예제 입력 A

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
2 2 1
..
..
0 0 0 0
2 2 1 .. .. 0 0 0 0
2 2 1
..
..

0 0 0 0

예제 출력 A

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
0
0
0

예제 입력 B

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
7 4 4
....
.##.
..#.
#.#.
#...
#.##
#.##
1 1 7 2
7 4 4 .... .##. ..#. #.#. #... #.## #.## 1 1 7 2
7 4 4
....
.##.
..#.
#.#.
#...
#.##
#.##
1 1 7 2

예제 출력 B

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
3
3
3

예제 입력 C

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
7 4 4
....
.##.
.#..
.#.#
...#
##.#
##.#
1 4 7 3
7 4 4 .... .##. .#.. .#.# ...# ##.# ##.# 1 4 7 3
7 4 4
....
.##.
.#..
.#.#
...#
##.#
##.#
1 4 7 3

예제 출력 C

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
3
3
3

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

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

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

예제 입력 D

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
3 3 3
..#
..#
#..
1 1 3 3
3 3 3 ..# ..# #.. 1 1 3 3
3 3 3
..#
..#
#..
1 1 3 3

예제 출력 D

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
3
3
3

통과된 코드

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#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;
}
#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; }
#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;
}

댓글 달기

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