본문 바로가기
PS 문제 풀이/Baekjoon

[BOJ] 백준 15665 N과 M(11)

by 까망 하르방 2021. 5. 9.
반응형

출처https://www.acmicpc.net/problem/15665  

Approach

▶ 순열과 조합 (백준 N과 M 시리즈) 

 

순열과 조합 (백준 N과 M 시리즈)

순열과 조합 순열(Permutation) / 조합(Combination)에서 개수를 구하는 경우에는 아래 공식을 이용하면 되지만 순열 및 조합으로 경우의 수가 필요한 경우에는 재귀를 이용해야한다. ① P(4, 3) = 4 x 3 x 2

zoosso.tistory.com

 

[BOJ] 15656 N과 M(7) 문제와 달리 주어지는 Input Data가 중복이 있을 수 있다.

따라서 중복 없는 순열을 구현하면서 이미 선택한 숫자인지도 판단하여야 한다.

 

이는 정렬된 Input Data에서 지역 변수 하나로 쉽게 판단할 수 있다.

"prev" 라는 이전에 선택된 숫자를 담아서 중복 되었는지를 알 수 있다.

 

전역 변수로 두지 못하는 것은 재귀함수로 비교할 때, 첫번째로 선택되는 숫자가

prev와 관계없이 선택되어지기 위함이다.

 


C / C++

#include <stdio.h>

const int MAX_N = 8 + 2;
int N, M, ans[MAX_N], arr[MAX_N], trr[MAX_N];

void input()
{
    scanf("%d %d", &N, &M);
    for (int i = 0; i < N; ++i)
    {
        scanf("%d", &arr[i]);
    }
}

void mergeSort(int start, int end) {
    // 0. base condition
    if (start >= end) return;
    // 1. divide
    int mid = (start + end) / 2;
    // 2. conquer
    mergeSort(start, mid);
    mergeSort(mid + 1, end);
    // 3. merge
    int i = start, j = mid + 1, k = start;
    while (i <= mid && j <= end) {
        if (arr[i] < arr[j])
            trr[k++] = arr[i++];
        else
            trr[k++] = arr[j++];
    }
    while (i <= mid) trr[k++] = arr[i++];
    while (j <= end) trr[k++] = arr[j++];
    // 4. copy
    for (i = start; i <= end; ++i) {
        arr[i] = trr[i];
    }
}

void DFS(int depth) {
    if (depth == M) {
        for (int i = 0; i < M; ++i) {
            printf("%d ", ans[i]);
        }
        printf("\n");
        return;
    }
    int prev = -1;
    for (int i = 0; i < N; ++i) {
        if (prev == arr[i]) continue;
        prev = ans[depth] = arr[i];
        DFS(depth + 1);
        ans[depth] = 0;
    }
}

int main() {
    // freopen("input.txt", "r", stdin);
    input();
    mergeSort(0, N - 1);
    DFS(0);
}

 

Java

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class Main {
    
    static int N, M;
    static List<Integer> list;
    static BufferedWriter log;
    static Map<String, String> map;
    
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        log = new BufferedWriter(new OutputStreamWriter(System.out));
        
        N = Integer.parseInt(sc.next());
        M = Integer.parseInt(sc.next());
        list = new ArrayList<>();
        
        for(int i=0; i<N; i++) {
            list.add(Integer.parseInt(sc.next()));
        }
        
        Collections.sort(list);
        
        List<Integer> answer = new ArrayList<>();
        map = new HashMap<String, String>();
        permutation(answer);
        
        log.flush();
    }
    
    private static void permutation(List<Integer> answer) throws IOException{
        if(answer.size() == M) {
            String str = "";
            for(int i=0; i < M; i++) {
                str += answer.get(i);
            }
            // 기존에 없는 결과이면
            if(map.get(str) == null) {
                for(int i=0; i < answer.size(); i++) {
                    log.write(answer.get(i) + " ");
                }
                log.write("\n");
                map.put(str, str);
            }

            return;
        }
        
        // 중복을 제거한 순열과의 차이는 방문표시를 하지 않는 것이다.        
        for(int i=0; i<N; i++) {
            answer.add(list.get(i));
            permutation(answer);
            // 방금 넣었던 것을 제거하고 다음 for문을 돌수 있도록
            answer.remove(answer.size()-1);
        }
    }
}

 

Reference

합병 정렬(Merge Sort) 

순열과 조합 (백준 N과 M 시리즈) 

[BOJ] 15656 N과 M(7)

 

 

반응형

'PS 문제 풀이 > Baekjoon' 카테고리의 다른 글

[BOJ] 백준 15829 Hashing  (0) 2021.05.10
[BOJ] 백준 15666 N과 M(12)  (0) 2021.05.09
[BOJ] 백준 15664 N과 M(10)  (0) 2021.05.09
[BOJ] 백준 15656 N과 M(7)  (0) 2021.05.09
[BOJ] 백준 15655 N과 M(6)  (0) 2021.05.09

댓글