티스토리 뷰
A] [징검다리 0] [징검다리 1] ... [징검다리 N-1] [B
철수는 다리가 짧아 징검다리를 한번에 한칸, 혹은 두칸만 건널 수 있다.
징검다리가 N개 있을때의 철수가 A에서 B로 이동할수 있는 경로의 수를 모두 구하라.
(아래 추가조건은 풀어도 되고, 안풀어도 되는 문제)
추가 조건1: '징검다리 p'는 너무 미끄러워 밟을 수 없다.
추가 조건2: 영희는 다리가 길어 징검다리를 한번에 한칸, 두칸, 혹은 세칸 건널 수 있다.
예(기본 문제 기준):
N == 0
A] [B
path 1: A -> B
N == 1
A] [징검다리 0] [B
path 1: A -> 0 -> B
path 2: A -> B
N == 2
A] [징검다리 0] [징검다리 1] [B
path 1: A -> 0 -> 1 -> B
path 2: A -> 1 -> B
path 3: A -> 0 -> B
예(추가조건 1기준):
N == 3, p == 2
A] [징검다리 0] [징검다리 1] [징검다리 2] [B
path 1: A -> 0 -> 1 -> B
path 2: A -> 1 -> B
징검다리 2가 미끄럽기때문에 2를 밟는 path인 0 -> 2, 1 -> 2, 2 -> B 가 불가능하다.
------------------------
일단 추가조건 없이 푸는 것은 일전에 풀었던 계단 올라가는 경우의 수와 비슷하게 재귀나 DP로 풀 수 있다.
N의 제한조건이 없지만, 가능경로의 수가 int 범위를 넘지 않기 위해서는 N<=30가 적절하다고 나름의 가정을 하겠다.
1 2 3 4 5 6 7 | int steppingStone(int N) { if(N < 0) return 0; if(N == 0) return 1; if(N == 1) return 2; return steppingStone(N-1) + steppingStone(N-2); } |
코드로는 간단하지만, 이걸 이해하기 위해서는 트리와 재귀에 대한 기본적 지식이 필요하다.
이 설명을 능숙하게 하기 위해서는 앞으로 많은 연습이 필요할 듯 하다.
추가 조건1: '징검다리 p'는 너무 미끄러워 밟을 수 없다.
처음에 Brute force하게 작성한 코드는 기존과 같지만 현재 위치 앞 1칸 or 2칸에 '징검다리 p'가 존재하는지 여부에 대해 신경쓰면서 구현했다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | int ss1(int N,int p) { if(N < 0) return 0; if(N == 0) return 1; if(N == 1) { if(N-1 == p) return 1; else return 2; } if(N-1 == p) return ss1(N-2, p); if(N-2 == p) return ss1(N-1, p); return ss1(N-1,p) + ss1(N-2,p); } |
그런데 생각해보니 철수는 다리가 짧아 최대 두칸밖에 가지 못하므로 징검다리 p를 피해 건너는 방법은 한가지 뿐이다.
ㄱ. 징검다리 p가 철수 앞 어딘가에 있다면
ㄴ. A에서 '징검다리 p-1'까지 이동한다. (처음의 steppingStone 함수를 이용)
ㄷ. '징검다리 p-1'에서 한번에 두칸을 건너 '징검다리 p+1'로 이동한다.
ㄹ. B까지 이동한다. (처음의 steppingStone 함수를 이용)
하면 아래와 같은 코드가 작성된다.
1 2 3 4 5 6 7 8 9 | int addition(int N, int p) { int frontP = steppingStone(p-1); int backP = steppingStone(steppingStone((N-1)-(p+1))); if(frontP == 0) frontP = 1; if(backP == 0) backP = 1; return (frontP * backP); } | cs |
이렇게 한다면, 시간복잡도는 다르지 않겠지만 좀 더 이해하기 쉽고, 가독성이 좋은 함수를 작성할 수 있다.
테스트 결과 아래와 같다.
답이 없어서 채점도 못해봤다. 추가조건2는 다음에 시간날 때 풀어야겠다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | int main() { int N; int p; //추가조건 없이 cin >> N; // 20 cout << steppingStone(N) << endl; // 17711 // 추가조건1 bruteForce ver cin >> N >> p; // 20 13 cout << ss1(N, p) << endl; // 4901 // 추가조건1 간략화 버전 cin >> N >> p; // 20 13 cout << addition(N, p) << endl; // 4901 return 0; } |
'Dev: 개발 > Algorithm' 카테고리의 다른 글
문자열에 포함된 문자들이 전부 유일한지 검사하는 알고리즘을 구현하라. (0) | 2016.09.11 |
---|---|
한 쌍의 수를 이동 없이 바꾸는 함수를 작성하라. (임시변수는 사용할 수 없다.) (0) | 2016.09.11 |
두 개의 Stack으로 하나의 Queue를 구현하라. (0) | 2016.08.24 |
코딩 인터뷰 스터디에 가입했다. (0) | 2016.08.23 |