<수열 추측하기>
: 가장 윗줄에 1부터 N까지의 숫자가 한 개씩 적혀 있다. 그리고 둘째 줄부터 차례대로 파스칼의 삼각형처럼 위의 두개를 더한 값이 저장되게 된다. 예를 들어 N이 4이고 가장 윗 줄에 3 1 2 4가 있다고 했을 때, 다음과 같은 삼각형이 그려진다.
N과 가장 밑에 있는 숫자가 주어져 있을 때 가장 윗줄에 있는 숫자를 구하는 프로그램을 작성한다. 단, 답이 여러가지가 나오는 경우에는 사전순으로 가장 앞에 오는 것을 출력해야 한다.
(첫 번째 줄에 두 개의 정수 N(1<=N<=10)과 F가 주어진다. 가장 위에 들어갈 N개의 숫자를 빈 칸을 사이에 두고 출력한다.)
- 그림을 그려본다.
그러면 아래처럼 나오는데, 결국 숫자의 위치에 따라 몇 번을 더해야 하는지 개수가 정해진다.- 다른 예시도 한 번 봐보자.
결국 n-1C0 ... n-1Cn-1을 구해야 하는 것이다.
- 그렇다면 이제 문제를 풀어보자. 1부터 N까지의 숫자가 주어지면, 이 숫자가 어떻게 배치돼 있느냐에 따라서 결과가 달라진다. 그러므로 우선 앞에서 배운 순열(1,2,3,4 / 1,2,4,3 / ...)이 들어가고, 이미 구했던 값을 중복해서 구할 필요는 없으므로 메모이제이션 또한 넣어보자.
규칙을 배열로 만들고(+콤비네이션계산(combi함수)), DFS에서 순열 만들어서 합을 구하자.- 정리하자면, 규칙을 만들기 위해 for문을 돌려서 combi함수 호출해서 계산하여 b배열 완성하고, DFS-else문에서 순열 만들어서 합을 구해서(p배열 이용), DFS-if문에서 검증하기.
- flag 변수가 있는 이유는 가장 앞에 오는 것을 출력하라고 했으므로.
3. 정답
<script> function solution(n, f){ let answer, flag=0; let dy= Array.from(Array(11), () => Array(11).fill(0)); //n의 범위가 1<=N<=10이라고 했으므로. 메모이제이션 let ch=Array.from({length:n+1}, ()=>0); //for문을 1부터 n까지 돌리므로, 길이를 n으로 할 경우 모자란다.(인덱스때문에) let p=Array.from({length:n}, ()=>0); //순열 let b=Array.from({length:n}, ()=>0); //규칙 function combi(n, r){ //메모이제이션 if(dy[n][r]>0) return dy[n][r]; if(n===r || r===0) return 1; else return dy[n][r]=combi(n-1, r-1)+combi(n-1, r); } function DFS(L, sum){ if(flag) return; if(L===n && sum===f){ answer=p.slice(); flag=1; //답이 구해졌으면 끝낸다. } else{ for(let i=1; i<=n; i++){ //순열만들기(1,2,3,4 / 1,2,4,3 / ...) + 값(규칙) //1부터 돌리는 이유 : 순열을 구하기 위한 것이므로 1,2,3,4의 수가 쓰여야 하므로 if(ch[i]===0){ ch[i]=1; p[L]=i; DFS(L+1, sum+(b[L]*p[L])); //위치에 따라 곱해야 할 개수가 정해진다고 했다. 계산(개수*값) ch[i]=0; } } } } for(let i=0; i<n; i++){ //규칙(1,3,3,1) //0부터 돌리는 이유 : 콤비네이션 r이 0부터 3까지 쓰이므로 b[i]=combi(n-1, i); //b[0]=3C0, b[1]=3C1, b[2]=3C2, b[3]=3C3 } DFS(0, 0); return answer; } console.log(solution(4, 16)); </script>
<script> //ch배열 인덱스가 헷갈려서 그냥 이렇게 바꿔버림 function solution(n, f){//answer, flag, dy, ch, p(순열), b(규칙) /L, sum let answer, flag = 0; let dy = Array.from(Array(n), ()=> Array(n).fill(0)); let ch = Array.from({length:n}, ()=>0); let p = Array.from({length:n}, ()=>0); let b = Array.from({length:n}, ()=>0); function combi(n, r){ if(dy[n][r]>0) return dy[n][r]; if(n===r || r===0) return 1; else return dy[n][r] = combi(n-1, r-1) + combi(n-1, r); } function DFS(L, sum){ if(flag) return; if(L===n && sum === f){ answer = p.slice(); flag = 1; }else{ for(let i = 1; i <= n; i ++){ if(ch[i-1] === 0){ ch[i-1] = 1; p[L] = i; DFS(L+1, sum+(p[L]*b[L])); ch[i-1] = 0; } } } } for(let i = 0; i < n; i ++){ b[i] = combi(n-1, i); } DFS(0,0); return answer; } console.log(solution(4, 16)); </script>