개발 공부~

[DFS, 메모이제이션] 수열 추측하기 본문

코딩테스트/기타

[DFS, 메모이제이션] 수열 추측하기

머밍 2024. 11. 16. 00:47

설명

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

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

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

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

입력

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

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

출력

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

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

예시 입력 1 

4 16

예시 출력 1

3 1 2 4

 

 

내 풀이 - 다른 풀이 참고

 

문제 설명

 

이 문제의 핵심은 "합을 어떻게 구하는가"이다

 

예시의 3 1 2 4라는 순열로 합을 풀어서 구하면

3 + 1+1+1 + 2+2+2 + 4

맨 왼쪽 오른쪽은 한번씩, 중앙 두개는 3개씩 들어가 있다

개수로만 보면 1개 3개 3개 1개이다

 

즉, n이 4이기에 4-1C0, 4-1C1, 4-1C2, 4-1C3 => 즉 n이 3일때 r이 0부터 n까지의 개수와 같다

따라서 각 숫자와 이에 해당하는 이항 계수를 곱한 뒤의 총합이 f이다

 

이 점을 알고 

https://better21.tistory.com/191

 

[DFS] 순열 구하기 .java

문제10이하의 N개의 자연수가 주어지면 이 중 M개를 뽑아 일렬로 나열하는 방법을 모두 출력합니다입력설명첫 번째 줄에 자연수 N(3출력설명첫 번째 줄에 결과를 출력합니다.출력순서는 사전순

better21.tistory.com

https://better21.tistory.com/192

 

[메모이제이션] 조합의 경우의 수

설명로 계산합니다.하지만 여러분은 이 공식을 쓰지않고 다음 공식을 사용하여 재귀를 이용해 조합수를 구해주는 프로그램을 작성하세요.입력첫째 줄에 자연수 n(3출력첫째 줄에 조합수를 출력

better21.tistory.com

이 두 글에 있는 코드를 참고하면 수월하게 풀 수 있었지만 저 계산식을 구하지 못해 결국 다른 풀이를 보고 풀었다

import java.util.Scanner;


public class Main {
    static int[][] dy  =new int[11][11];//n최대 11
    static int n, f;
    static int[] c, arr, visited;// c이항 계수 배열, arr순열을 저장, visited방문 배열
    static boolean find = false;//하나의 값을 찾음


    public static int cdfs(int n, int r) {
        if(dy[n][r] > 0) return dy[n][r];//이미 계산된 값이 있으면 반환 (메모이제이션)
        if(n==r || r == 0) return 1;//nC0 = 1, nCn = 1
        else return dy[n][r] = cdfs(n-1,r-1) + cdfs(n-1,r);

    }
    public static void dfs(int L, int sum) {//모든 순열을 생성하며 합을 계산
        if(find) return;//찾았으면 더 이상 탐색하지 않음
        if(L == n) {//모든 숫자를 다 사용한 경우
            if(sum==f) {
                for(int x : arr) System.out.print(x + " ");
                find = true;
            }

        }else {
            for(int i =1; i <=n; i++) {//순열에 들어갈 숫자
                //아직 방문하지 않은 숫자인 경우
                if(visited[i] == 0) {
                    visited[i] = 1;
                    arr[L] = i;
                    dfs(L+1,sum+(arr[L] * c[L]));
                    visited[i] = 0;//미방문처리
                }

            }
        }

    }
    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        f = sc.nextInt();
        arr = new int[n];
        c = new int[n];
        visited = new int[n+1];//인덱스가 값 -> n까지 사용

        for(int i = 0; i < n; i++) {
            c[i] = cdfs(n-1, i);// n-1Ci를 계산하여 c 배열에 저장

        }
        dfs(0,0);


    }

}

'코딩테스트 > 기타' 카테고리의 다른 글

[DFS] 미로 탐색  (0) 2024.11.16
[DFS] 조합 구하기 .java  (0) 2024.11.16
[메모이제이션] 조합의 경우의 수  (0) 2024.11.16
[DFS] 순열 구하기 .java  (1) 2024.11.15
[DFS] 동전교환 .java  (3) 2024.11.15