백준 1904 JavaScript
수정하기
문서 생성 2022-04-29 12:27:38 최근 수정 2022-04-29 20:53:15
문제
풀이
문제를 풀기 위해 나오는 2진 수열을 나열해보자.
// 1, 00 이 적힌 타일// N=1 => 1// N=2 => 00, 11// N=3 => 001, 111, 100// N=4 => 0011, 0000, 1001, 1100, 1111// N=5 => 00111, 00001, 10011, 11001, 11111 -> N=4에 1 추가// 10000, 11100, 00100, 11000 -> N=3에 00추가// N=6 => 001111, 000011, 100111, 110011, 111111// 100001, 111001, 001001, 110001 -> N=5에 1 추가// 001100, 000000, 100100, 110000, 111100 -> N=4에 00추가
위와 같이 나열하면 규칙을 발견할 수 있다. 사용할 수 있는 숫자 타일은 총 2가지 00
과 1
이므로 두 가지 방법으로 조합할 수 있다.
N
자리 수열은N-1
자리 수열에 하나의 숫자를 추가해야 하는데00
과1
중1
만 가능하다. 따라서N-1
자리로 만드는 수열들에1
을 추가하면 된다.N
자리 수열은N-2
자리 수열에 두자리 숫자를 추가하면N
자리가 되는데00
을 추가하면 된다.
따라서 다음과 같은 결론이 내려진다. 이전에 계산해 놓은 값을 활용할 수 있다. 즉, Dynamic-Programming으로 해결해볼 수 있겠다.
N자리로 이뤄진 2진 수열의 개수 = N-1자리로 이뤄진 2진 수열의 개수 + N-2자리로 이뤄진 2진 수열의 개수
전체코드는 다음과 같다. 주의할 점은 결과값에만 15746
로 나머지 연산을 하니 메모리 초과가 났다. 이유는 최대값인 1,00,000
을 넣어보니 알 수 있었다. 숫자가 너무 커서 였다. 그래서 DP배열의 값을 구할 때마다 15746
으로 나눴다.
const readFileSyncPath = require('path').basename(__filename).replace(/js$/, 'txt')// const readFileSyncPath = '/dev/stdin';const input = require('fs').readFileSync(readFileSyncPath).toString().trim().split('\n')// 1, 00 이 적힌 타일// N=1 => 1// N=2 => 00, 11// N=3 => 001, 111, 100// N=4 => 0011, 0000, 1001, 1100, 1111// N=5 => 00111, 00001, 10011, 11001, 11111 -> N=4에 1 추가// 10000, 11100, 00100, 11000 -> N=3에 00추가// N=6 => 001111, 000011, 100111, 110011, 111111// 100001, 111001, 001001, 110001 -> N=5에 1 추가// 001100, 000000, 100100, 110000, 111100 -> N=4에 00추가// N자리로 이뤄진 2진 수열의 개수 = N-1자리로 이뤄진 2진 수열의 개수 + N-2자리로 이뤄진 2진 수열의 개수const N = Number(input[0])const DP = Array.from({ length: N + 1 }).fill(0)DP[1] = 1DP[2] = 2for (let i = 3; i <= N; i++) {DP[i] = (DP[i - 2] + DP[i - 1]) % 15746}console.log(DP[N])