수열 추측하기

문제

설명

가장 윗줄에 1부터 N까지의 숫자가 한 개씩 적혀 있다. 그리고 둘째 줄부터 차례대로 파스칼의 삼각형처럼 위의 두개를 더한 값이 저장되게 된다.

예를 들어 N이 4 이고 가장 윗 줄에 3 1 2 4 가 있다고 했을 때, 다음과 같은 삼각형이 그려진다.

https://cote.inflearn.com/public/upload/e2f3cae26a.jpg

N과 가장 밑에 있는 숫자가 주어져 있을 때 가장 윗줄에 있는 숫자를 구하는 프로그램을 작성하시오.

단, 답이 여러가지가 나오는 경우에는 사전순으로 가장 앞에 오는 것을 출력하여야 한다.

입력

첫째 줄에 두개의 정수 N(1≤N≤10)과 F가 주어진다.

N은 가장 윗줄에 있는 숫자의 개수를 의미하며 F는 가장 밑에 줄에 있는 수로 1,000,000 이하이다.

출력

첫째 줄에 삼각형에서 가장 위에 들어갈 N개의 숫자를 빈 칸을 사이에 두고 출력한다.

답이 존재하지 않는 경우는 입력으로 주어지지 않는다.

예시 입력 1

4 16

예시 출력 1

3 1 2 4

해결방법

75.png

  • 위와 같은 사진 처럼 규칙을 발견하여 적용하고, 답을 찾는다.
  • 여기에서는 각 원소들이 몇번 더해지는 지에 대해 규칙을 찾을 수 있으며, 이는 조합과 동일하다 문제 기준으로 첫번째 원소는 1번 더하고, 두번째 원소는 3번 더하고 … 를 가지는데 이는 조합으로 표현하면 3C0, 3C1 … 과 같다. 따라서, 각 원소의 값과 해당 조합수를 곱한 후 다 더해주면 마지막 값이 나오게 된다.
  • n 개의 수에서, m개를 뽑아 만들 때 합이 sum이 되는 경우를 구하는 재귀함수 구조를 알아두는 것이 좋다.

코드

import java.util.ArrayList;
import java.util.Scanner;

class Main {
    static int[] b, p, ch; // 순서대로 조합 저장하기 위한 배열, 재귀 돌리는 숫자 원소 배열, 숫자 사용 했는지 체크하는 배열
    static int n, f;
    boolean flag = false; // 종료를 위한 플래그
    int[][] dy = new int[35][35];

    // 조합 구하는 함수
    public int combi(int n, int 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);
    }

    public void DFS(int L, int sum) {
        // 불필요한 호출을 리턴시키기 위한 조건
        if (flag) return;
        if (L == n) { // 특정 레벨에 도달 시
            if (sum == f) { // 구하고자 하는 수와 같다면
                // 정답을 프린트하고, 조건을 True로 바꿔 종료
                for (int x : p) System.out.print(x + " ");
                flag = true;
            }
        } else {
            // 재귀 호출
            for (int i = 1; i <= n; i++) {
                if (ch[i] == 0) {
                    // 사용 여부 체크
                    ch[i] = 1;
                    p[L] = i;
                    // 각 원소와 조합 결과 합친 것을 더하여 계속 넘기면서 합이 주어진 마지막 값과 같을 때까지 재귀한다.
                    DFS(L + 1, sum + (p[L] * b[L]));
                    ch[i] = 0;
                }
            }
        }
    }

    public static void main(String[] args) {
        Main T = new Main();
        Scanner kb = new Scanner(System.in);
        n = kb.nextInt();
        f = kb.nextInt();
        b = new int[n];
        p = new int[n];
        ch = new int[n + 1];
        for (int i = 0; i < n; i++) {
            b[i] = T.combi(n - 1, i);
        }
        T.DFS(0, 0);
    }
}

© 2024. Chiptune93 All rights reserved.