[백준][15652번] N과 M(4)

Updated:

문제 URL

https://www.acmicpc.net/problem/15652 boj15652

내풀이

import java.io.*;
import java.util.StringTokenizer;

public class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    static int[] ans;

    public static void main(String[] args) throws IOException {
        StringTokenizer st = new StringTokenizer(br.readLine(), " ");
        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());
        ans = new int[m];
        cal(1, 0, n, m);
        bw.flush();
        bw.close();
    }
    //idx: 숫자
    //selectd:: 지금까지 선택된 수의 개수
    public static void cal(int idx, int selected, int n, int m) throws IOException {
        if (selected == m) {
            StringBuilder sb = new StringBuilder();
            for (int a : ans)
                sb.append(a + " ");
            bw.write(sb.toString());
            bw.newLine();
            return;
        }
        if (idx > n) return;
        //수를 선택
        ans[selected] = idx;
        cal(idx, selected + 1, n, m);
        //수를 선택하지 않을경우
        ans[selected] = 0;
        cal(idx + 1, selected, n, m);
    }
}

다른 풀이법(순서관점) **

import java.util.*;
public class Main {
    static boolean[] c = new boolean[10];
    static int[] a = new int[10];
    static StringBuilder go(int index, int start, int n, int m) {
        if (index == m) {
            StringBuilder sb = new StringBuilder();
            for (int i=0; i<m; i++) {
                sb.append(a[i]);
                if (i != m-1) sb.append(" ");
            }
            sb.append("\n");
            return sb;
        }
        StringBuilder ans = new StringBuilder();
        for (int i=start; i<=n; i++) {
            //if (c[i]) continue;
            c[i] = true;
            a[index] = i;
            ans.append(go(index+1, i, n, m));
            c[i] = false;
        }
        return ans;
    }   
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        System.out.print(go(0,1,n,m));
    }
}

다른 풀이법(선택관점) **

import java.util.*;
public class Main {
    static int[] cnt = new int[10];
    //idx: 숫자
    //selectd:: 지금까지 선택된 수의 개수
    static StringBuilder go(int index, int selected, int n, int m) {
        if (selected == m) {
            StringBuilder sb = new StringBuilder();
            for (int i=1; i<=n; i++) {
                for (int j=1; j<=cnt[i]; j++) {
                    sb.append(i);
                    sb.append(" ");
                }
            }
            sb.append("\n");
            return sb;
        }
        StringBuilder ans = new StringBuilder();
        if (index > n) return ans;
        // m-selected 에서 1까지 감소하는 순으로 한 이유는
        // 문제에서 전체수열 정렬해서 출력하라고해서
        for (int i=m-selected; i>=1; i--) {
          //cnt[i] = 수 i를 몇개포함
            cnt[index] = i;
            ans.append(go(index+1, selected+i, n, m));
        }
        cnt[index] = 0;
        ans.append(go(index+1, selected, n, m));
        return ans;
    }   
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        System.out.print(go(1, 0, n, m));
    }
}

느낀점

전형적인 브루트포스다. 앞에푼 N과M문제의 변형이 계속 나온다.

  • 풀이법(선택관점) 각각의 자연수를 선택하는 경우와 선택하지 않는경우가 있다. 하지만, 중복선택가능하기 떄문에, 선택하는 경우를 i개 선택하는 경우로 세분화해야한다.
  • 시간복잡도 : O(2n)

Leave a comment