Suhwanc

문제 링크 : https://www.acmicpc.net/problem/6603

 

6603번: 로또

문제 독일 로또는 {1, 2, ..., 49}에서 수 6개를 고른다. 로또 번호를 선택하는데 사용되는 가장 유명한 전략은 49가지 수 중 k(k>6)개의 수를 골라 집합 S를 만든 다음 그 수만 가지고 번호를 선택하는 것이다. 예를 들어, k=8, S={1,2,3,5,8,13,21,34}인 경우 이 집합 S에서 수를 고를 수 있는 경우의 수는 총 28가지이다. ([1,2,3,5,8,13], [1,2,3,5,8,21], [1,2,3,5,8,34], [1,2

www.acmicpc.net

 

문제

독일 로또는 {1, 2, ..., 49}에서 수 6개를 고른다.

로또 번호를 선택하는데 사용되는 가장 유명한 전략은 49가지 수 중 k(k>6)개의 수를 골라 집합 S를 만든 다음 그 수만 가지고 번호를 선택하는 것이다.

예를 들어, k=8, S={1,2,3,5,8,13,21,34}인 경우 이 집합 S에서 수를 고를 수 있는 경우의 수는 총 28가지이다. ([1,2,3,5,8,13], [1,2,3,5,8,21], [1,2,3,5,8,34], [1,2,3,5,13,21], ..., [3,5,8,13,21,34])

집합 S와 k가 주어졌을 때, 수를 고르는 모든 방법을 구하는 프로그램을 작성하시오.

 

입력

입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스는 한 줄로 이루어져 있다. 첫 번째 수는 k (6 < k < 13)이고, 다음 k개 수는 집합 S에 포함되는 수이다. S의 원소는 오름차순으로 주어진다.

입력의 마지막 줄에는 0이 하나 주어진다. 

 

출력

각 테스트 케이스마다 수를 고르는 모든 방법을 출력한다. 이때, 사전 순으로 출력한다.

각 테스트 케이스 사이에는 빈 줄을 하나 출력한다.

 

풀이

조합 문제이다.

이번엔 이전 글에서 설명한 next_permutation 함수를 이용해 조합을 구현해보겠다.

우선 조합을 구현하는데에 이 두가지만 알면 의외로 간단하다.

n개의 수 중 k개를 뽑는다고 하자.

1. vector에 k개의 1을 추가한다.

2. 이후 n-k개의 0 또는 2를 추가한다.

보통 2번 과정에서 0을 추가하는게 일반적이나, 2를 추가해도 별 의미는 없다.

다만, 나중에 뽑을 때 오름차순으로 뽑느냐, 내림차순으로 뽑느냐에 따라 갈리는데 이후에 설명하도록 하겠다.

코드로 표현하자면,

vector ind;
int k = 6; //6개 뽑기

for (int i = 0; i < k; i++) { //k개의 1 추가
ind.push_back(1);
}
for (int i = 0; i < s.size() - k; i++) { //전체크기 - k개의 0 추가
ind.push_back(2);
}
sort(ind.begin(), ind.end());

 

이런식으로 초기 vector를 만들어주고, 

do ~ while문으로 next_permutation을 구현하면서, 배열의 index가 1인것을 print하면 k개의 정렬된 조합이 나온다.

소스코드를 보자.

 

소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
 
int main()
{
    int first_check = 1;
    while (1) {
        int t; scanf("%d"&t);
        if (t == 0break;
        vector<int> s;
        if (first_check == 0printf("\n");
        first_check = 0;
        for (int i = 0; i < t; i++) {
            int temp; scanf("%d"&temp);
            s.push_back(temp);
        }
        vector<int> ind;
        int k = 6//6개 뽑기
        
        for (int i = 0; i < k; i++) { //k개의 1 추가
            ind.push_back(1);
        }
        for (int i = 0; i < s.size() - k; i++) { //전체크기 - k개의 0 추가
            ind.push_back(2);
        }
        sort(ind.begin(), ind.end());
        do {
            for (int i = 0; i < ind.size(); i++) {
                if (ind[i] == 1) {
                    printf("%d ", s[i]);
                }
            }
            printf("\n");
        } while (next_permutation(ind.begin(), ind.end()));
        
    }
    return 0;
}
cs

이 문제에선 n-k개의 수를 2로 넣었다.

그 이유는 출력을 사전 순(오름차순)으로 출력하라는 조건때문인데,

next_permutation 함수는 오름차순으로 수열을 구하기때문에

1 1 1 1 1 1 2 2

1 1 1 1 1 2 1 2

1 1 1 1 1 2 2 1 

...

이런식으로 수열을 뽑게되면, 처음부터 차례대로 출력이 가능하다.

반면 0을 넣게 되면,

0 0 1 1 1 1 1 1

0 1 0 1 1 1 1 1

0 1 1 0 1 1 1 1

...

이런식으로 수열을 구하기 때문에 뒤 index부터 출력이 되어 내림차순으로 출력이 된다.

 

이런 사실은 문제에 맞춰 바꿔주면 되겠다.

개발환경 : Visual Studio 2019

지적, 조언 언제든지 환영입니다~~

'백준 문제풀이' 카테고리의 다른 글

백준 1722번 순열의 순서  (0) 2020.01.06
백준 10972,10973,10974 수열 구하기 문제  (0) 2020.01.06
백준 10971번 외판원 순회2  (1) 2020.01.03
백준 10819번 차이를 최대로  (0) 2020.01.03
백준 11723번 집합  (0) 2020.01.03