본문 바로가기
Algorithm/백준풀이

[알고리즘 문제풀이] 백준 - N과M(2) / JAVA(자바)

by 계범 2022. 2. 6.

https://www.acmicpc.net/problem/15650

 

15650번: N과 M (2)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해

www.acmicpc.net

 

선행학습: 재귀

 

/*
   1~N중에서 M개를 고른 수열
   오름차순 정렬이고 중복 없으므로
   visited 개념으로 리스트를 만들어서 사용했으면 넘어갈것
   그리고 다음 고른 숫자가 기존에 고른것보다 작으면 넘어갈것

*/


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

public class Main {

    public static int n;
    public static int m;
    
    // 숫자 배열
    public static int[] arr;

    // 선택숫자 배열
    public static int[] choice;


    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        StringTokenizer st = new StringTokenizer(br.readLine()," ");

        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());
        
        //숫자 배열 길이 생성
        arr = new int[n+1];

        // 선택담을 배열 생성
        choice = new int[m];

        solve(0);
    }

    public static void solve(int stage){

        // 다 골랐을때
        if(stage == m){
            //선택 배열 돌면서 출력
            for(int idx = 0; idx < m; idx++){
                System.out.print(choice[idx] + " ");
                }
            System.out.println();
            return;
        }

        // 숫자를 돌면서 고르기
        for(int i =1; i <= n; i++){
            // 고르지 않은 숫자일때
            if(arr[i] == 0){
                // 한개이상의 숫자를 골랐다면 현재 고른 숫자가
                // 기존의 고른 숫자보다 커야함 크지않으면 다음숫자확인
                if(stage > 0 && i < choice[stage-1]) continue;

                // 고른숫자 담기
                choice[stage] = i;
                // 숫자 사용한것으로 표기
                arr[i] = 1;
                // 다음숫자 고르러 가기
                solve(stage+1);
                // 초기화
                arr[i] = 0;
            }
        }
        return;
    }
}

 

2) pnum을 이용한 풀이

 

/*
    1. n과 m 을 받기

    2. n까지의 자연수 중에서 m개의 숫자를 고르기

    3. 1~n까지의 숫자 중에서 고를 때마다, 다시 함수를 불러서 다음 숫자를 고를 것.
    3-1) 함수에서 숫자를 고를땐, 골랐던것은 고르면 안됨.
    3-2) 오름차순이어야함.

    4. 다 골랐을때, 고른 숫자를 출력할 것.
*/

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

public class Test {

    public static int n, m;
    public static boolean[] visited;
    public static int[] choice;
    public static BufferedWriter bw;
    public static void main(String[] args) throws IOException{
        // 문자열 받기
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // 문자열 나누기
        StringTokenizer st = new StringTokenizer(br.readLine());
        
        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());

        // 현재 숫자를 사용했었는지 체크하기위한 배열
        visited = new boolean[n+1];
        // 고른 숫자를 저장해두기 위한 배열
        choice = new int[m];

        solve(0,0); // 숫자를 고를 함수
    }

    // 숫자를 고를 함수(stage: 숫자를 고른 갯수, pnum: 과거에 고른 숫자)
    public static void solve(int stage, int pnum){

        // 종료조건(m 개의 숫자를 다 골랐을때)
        if(stage == m){
            // 고른 숫자들을 출력
            for(int j = 0; j < m; j++){
                System.out.print(choice[j] + " ");
            }
            System.out.println();
            return;
        }

        // n까지의 숫자를 돌면서 고를 것(과거에 고른 숫자보다 1만큼 큰것부터 확인)
        for(int i = pnum +1; i <= n; i++){
            // 현재 숫자를 안골랐을때 고를 것.
            if(visited[i] == false){
                // 배열에 고른 숫자 담아두기
                choice[stage] = i;
                // 현재 숫자를 고른것으로 체크
                visited[i] = true;
                // 다음 숫자를 고르러 가기(pnum 현재 고른 숫자도 같이 넘기기)
                solve(stage+1,i);
                // 초기화작업(현재 숫자를 다시 고를 수 있게 하기 위해)
                visited[i] = false;
            }
        }
    }
}

댓글