-
백준 1600번 말이 되고픈 원숭이PS 2020. 2. 19. 13:13
https://www.acmicpc.net/problem/1600
1600번: 말이 되고픈 원숭이
첫째 줄에 자연수 K가 주어진다. 둘째 줄에 격자판의 가로길이 W, 세로길이 H가 주어진다. 그 다음 H줄에 걸쳐 W개의 숫자가 주어지는데, 0은 아무것도 없는 평지, 1은 장애물을 뜻한다. 장애물이 있는 곳으로는 이동할 수 없다. 시작점과 도착점은 항상 평지이다. W와 H는 1이상 200이하의 자연수이고, K는 0이상 30이하의 정수이다.
www.acmicpc.net
<접근방법>
bfs 문제 입니다.
전형적인 문제와 조금 다른 점이 있습니다.
원숭이가 같은 (y, x) 라는 좌표에 있더라도 능력이 몇 번 남았느냐에 따라 남은 결과가 달라진다는 것 입니다.
(y, x)에서 능력이 1번 남았을 때와 0번 남았을 때를 비교해보면 바로 알 수 있지요.
그래서 단순히 좌표만으로 중복체크를 한다면 안된다는 것 입니다.
그럼 중복체크를 어떻게 할까요?
같은 좌표와 같은 능력 횟수를 가지고 있다면 결과도 같겠죠?
그러므로 좌표에다가 능력까지 포함한 중복체크를 해줘야합니다.
이것은 중복체크배열을 3차원으로 하면 됩니다.
<코드>
#include <iostream> #include <algorithm> #include <queue> using namespace std; struct point { int y, x, cnt, time; }; int k, n, m, map[200][200]; int dy[12] = { 1, -1, 0, 0,-2, -1, 1, 2, 2, 1, -1, -2 }; int dx[12] = { 0, 0, 1, -1, 1, 2 ,2, 1, -1, -2, -2, -1 }; bool visit[200][200][30] = { false, }; int bfs() { queue<point> q; q.push({0, 0, k, 0}); visit[0][0][k] = true; while (!q.empty()) { point t = q.front(); q.pop(); if (t.y == n - 1 && t.x == m - 1) return t.time; for (int i = 0; i < 12; i++) { int ty, tx, tcnt = t.cnt, ttime = t.time + 1; if (i >= 4) { if (t.cnt == 0) break; tcnt -= 1; } ty = t.y + dy[i]; tx = t.x + dx[i]; if (ty < 0 || ty >= n || tx < 0 || tx >= m) continue; if (visit[ty][tx][tcnt] || map[ty][tx] == 1) continue; q.push({ty, tx, tcnt, ttime}); visit[ty][tx][tcnt] = true; } } return -1; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cin >> k; cin >> m >> n; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> map[i][j]; } } cout << bfs() << '\n'; return 0; }
<느낀 점>
-스택, 메모리, 힙 영역
반응형'PS' 카테고리의 다른 글
백준 14890번 경사로 (0) 2020.02.19 백준 1938번 통나무 옮기기 (0) 2020.02.19 백준 16397번 탈출 (0) 2020.02.19 백준 3055번 탈출 (0) 2020.02.19 백준 16947번 서울 지하철 2호선 (0) 2020.02.16