[백준] 15663번: N과 M (9)

프로타쿠·2024년 8월 2일

백준

목록 보기
10/24

Solved.ac 실버3
https://www.acmicpc.net/problem/15663

문제

설명

N개의 자연수와 자연수 M이 주어졌을 때, 아래 조건을 만족하는 길이가 M인 수열을 모두 구하는 프로그램을 작성하시오.

  • N개의 자연수 중에서 M개를 고른 수열

입력

첫째 줄에 N과 M이 주어진다. (1 ≤ M ≤ N ≤ 8)
둘째 줄에 N개의 수가 주어진다. 입력으로 주어지는 수는 10,000보다 작거나 같은 자연수이다.

출력

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

해결 Tip

알고리즘 분류

  • 백트래킹
  1. 신경써야 할 부분은 2가지이다.
    • 정답 배열에 들어간 입력받은 수는 어떤 것인가?
    • 새로운 수를 정답 배열에 넣으려고 입력받은 수들의 배열 A를 탐색할 때, 이미 등장한 수는 어떤 것인가?
  2. 첫번째는 전역 변수로 bool 배열 B1을 하나 선언하고, 함수 내에서 인덱서 i번째 수를 정답배열에 집어 넣을 땐 B1의 i번째 값을true, 함수가 종료되면 B1의 i번째 값을 false로 지정한다.
  3. 두번째는 지역 변수로 재귀함수 내에 bool 배열 B2를 크기가 10,001칸이 되도록 잡는다. (입력되는 수의 최댓값 = 10,000) 그리고 반복문을 돌면서 정답 배열에 집어넣은 수를 인덱스로 취급해서 B2의 값을 true로 바꿔준다.
  4. 정답 배열에 수를 집어넣을 때에는 조건문 "B1[i] == false && B2[A[i]] == false" 를 판단하면 된다.

코드

#include <bits/stdc++.h>
#define MAX_NUM 10000
#define fastio ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;

int N, M;
int A[8], ans[8];
bool out_check[8];

void solve(int len) {
    if (len == M) {
        for (int i=0 ; i < len ; i++)
            cout << ans[i] << ' ';
        cout << '\n';
        return;
    }
    else {
        bool in_check[MAX_NUM+1] = { 0,};
        for (int i=0 ; i < N ; i++) {
            if (!in_check[A[i]] && !out_check[i]) {
                in_check[A[i]] = true;
                out_check[i] = true;
                ans[len] = A[i];
                solve(len+1);
                out_check[i] = false;
            }
        }
    }
}

int main() {
    fastio;
    cin >> N >> M;
    for (int i=0 ; i < N ; i++)
        cin >> A[i];
    sort(A, A+N);
    solve(0);
	return 0;
}
profile
안녕하세요! 프로타쿠입니다

0개의 댓글