반응형
출처: https://www.acmicpc.net/problem/15665
Approach
[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
반응형
'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 |
댓글