반응형
외발 뛰기
어떻게 풀까?
한 지점에서 맵 만큼 오른쪽으로 이동하고 맵 만큼 아래쪽으로 이동해서, 해당 지점에서 끝날 수 있는지 값을 반환하면 됩니다.
다만, 해당 지점에 2번 이상 갈 수 있는 가능성이 존재합니다.
예를 통해 확인해 보겠습니다.
1 1 1 1
1 1 2 2
1 1 2 1
문제에서 주어진 맵은 위와 같습니다.
(2,2) 를 가는 방법은 (1,1) - (2,1) - (2,2), (1,1) - (1,2) - (2,2) 2가지 방법이 있습니다.
따라서, 이를 재귀 함수로 풀게 될 시에 solve(2,2)는 2번 해결할 것입니다.
이는 다른 지점에서도 마찬가지이고, 맵이 크면서 도착점에 가까울 수록 더 심해질 것입니다.
따라서, 해당 지점에서 끝나지 못한다면 이 결과를 저장하는 메모이제이션을 이용하면
해당 지점에서의 중복 계산을 피할 수 있습니다.
코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | #pragma once #include<cstdio> #include<cstring> //외발 뛰기 //알고스팟 //https://algospot.com/judge/problem/read/JUMPGAME int canEnd[100][100] = { 0 }; int map[100][100]; int n, c; bool check(int r, int c) { return r >= 0 && r < n && c >= 0 && c < n; } bool follow(int r, int c) { if (r == n - 1 && c == n - 1) { return true; } int &ret = canEnd[r][c]; if (ret == false) { return false; } if (check(r + map[r][c], c)) { ret = follow(r + map[r][c], c); if (ret) return true; } if (check(r, c + map[r][c])) { ret = follow(r, c + map[r][c]); if (ret) return true; } return false; } void init() { memset(canEnd, -1, sizeof(canEnd)); scanf("%d\n", &n); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { scanf("%d \n", &map[i][j]); } } } int main() { int t; scanf("%d\n", &t); const char s[2][4] = { "NO", "YES" }; while (t--) { init(); bool res = follow(0, 0); printf("%s\n", s[res]); } return 0; } | cs |
반응형
'공부 > 알고리즘 문제풀이' 카테고리의 다른 글
[알고스팟] 삼각형 위의 최대 경로 (0) | 2018.06.12 |
---|---|
[알고스팟] 와일드카드 (0) | 2018.06.12 |
[알고스팟] 팬 미팅 (0) | 2018.06.11 |
[알고스팟] 울타리 잘라내기 (0) | 2018.06.11 |
[알고스팟] 쿼드 트리 뒤집기 (0) | 2018.06.11 |