반응형

 

1. 개념 정리

조합 : 순서가 상관없음

순열 : 순서가 상관있음

중복 : 같은 아이템을 여러 번 뽑을 수 있는지 (중복조합 / 중복순열)

 

 

 

2. 문제 해결 방법

- k : 앞으로 뽑아야 할 크기

- Trivial Case : k가 0일 때

- Recursive Case (if k > 0) : 앞으로 K 개를 더 뽑아야 하므로 일단 1개를 뽑고 같은 함수를 이용해 k-1개를 더 뽑는다.

 

 

3. 예시

1) 공뽑기 : A, B, C, D, E, F,G가 적혀 있는 공 7개에서 3개를 뽑는 경우를 구하라

=> 순서가 상관없고 중복이 없으므로 "조합" 문제이다.


#include <stdio.h>

void pick(int n, int* bucket, int bucketSize, int k, char* balls){
    int i, lastIndex,smallest, item;
    if(k == 0){
        for(i=0; i<bucketSize; i++){
            printf("%c ", balls[bucket[i]]);
        }
        printf("\n");
        return;
    }
    
    lastIndex = bucketSize - k - 1;
    
    if(bucketSize == k){
        smallest = 0;
    } else {
        smallest = bucket[lastIndex] + 1;
    }
    
    for(item=smallest; item<n; item++){
        bucket[lastIndex+1] = item;
        pick(n, bucket, bucketSize, k-1, balls);
    }
}

int main(void) {
    
    int n = 7;
    char balls[7] = {'A','B','C','D','E','F','G'};
    int bucket[3];
    
    pick(n, bucket, 3, 3, balls);
    
    
    return 0;
}

 

 

 

 

2) 배우들 중 n명을 뽑아서 최우수, 우수상을 수여하기로 한다. 1명은 단 하나의 상만 받을 수 있다.

배우는 공유, 김수현, 송중기, 지성, 현빈 5명 중에서 선택한다고 하자. 어떤 경우가 가능한가?

=> 순서가 중요하고, 중복이 허용되지 않으므로 "순열" 문제이다.

 


#include <stdio.h>

int isIn(int* bucket, int size, int num){
    int i;
    for(i=0; i<size; i++){
        if(bucket[i] == num)
            return 1;
    }
    return 0;
}

void pick(int n, int* bucket, int bucketSize, int k, char balls[][10]){
    int i, lastIndex, item;
    if(k == 0){
        for(i=0; i<bucketSize; i++){
            printf("%10s", balls[bucket[i]]);
        }
        printf("\n");
        return;
    }
    
    lastIndex = bucketSize - k - 1;
    
    for(item=0; item<n; item++){
        if(!isIn(bucket, lastIndex+1, item)){
            bucket[lastIndex+1] = item;
            pick(n, bucket, bucketSize, k-1, balls);
        }
    }
}

int main(void) {
    
    int n = 5;
    char actors[5][10] = {"공유", "김수현", "송중기","지성", "현빈"};
    
    
    int bucket[2];
    
    pick(n, bucket, 2, 2, actors);
    
    
    return 0;
}

 

 

 

3) 4진법으로 만들 수 있는 n자리 수를 모두 나열하는 프로그램 작성하시오

입력 : 3  (3자리 수)

출력 : 000, 001, ..., 333 으로 나오면 된다.

=> 순서가 중요하고, 중복이 가능하므로 "중복순열" 문제이다. 

#include <stdio.h>

void pick(int n, int* bucket, int bucketSize, int k, int* balls){
    int i, lastIndex, item;
    if(k == 0){
        for(i=0; i<bucketSize; i++){
            printf("%d", balls[bucket[i]]);
        }
        printf("\n");
        return;
    }
    
    lastIndex = bucketSize - k - 1;
    
    for(item=0; item<n; item++){

        bucket[lastIndex+1] = item;
        pick(n, bucket, bucketSize, k-1, balls);
    
    }
}

int main(void) {
    
    int n = 4;
    int num[4] = {0,1,2,3};
    
    int bucket[3];
    
    pick(n, bucket, 3, 3, num);
    
    
    return 0;
}

 

 

 

4) 1부터 n까지의 연속되어 있는 수와 +/-를 이용해서 만들 수 있는 모든 수식을 그 결과와 함께 나열하시오

- 입력 : 2

- 출력:

 + 1 + 2 = 3

+ 1 -2 = -1

-1 + 2 = 1

-1 -2 = -3

 

=> 1과 2는 그대로 있고, +와 -를 이용해 중복순열을 처리하는 문제이다.

#include <stdio.h>

int charToInt(char x, int sum, int n){
    if(x == '+'){
        sum += n;
    } else {
        sum -= n;
    }
    return sum;
}

void func(int n, char bucket[2], int bucketSize, int k, char *balls){
    
    int i, j;
    int balls_idx = bucketSize - k;
    
    if(k == 0){
        int sum = 0;
        for(j=0; j<bucketSize; j++){
           
            printf("%c", balls[j]);
            printf("%d", j+1);
            sum = charToInt(balls[j], sum, j+1);
            
        }
        printf("=%d\n", sum);
        return;
    }
    
    for(i=0; i<bucketSize; i++){
        balls[balls_idx] = bucket[i];
        func(n, bucket, bucketSize, k-1, balls);
    }
}

int main(void) {
    
    char bucket[2] = {'+','-'};
    
    char answer[2];
    
    int n;
    
    scanf("%d", &n);
    
    func(n, bucket, 2, n, answer);
    
    
    return 0;
}

 

 

 

 

 

5) 1000,5000,10000원 짜리 지폐로 입력값을 만들 수 있는 모든 방법을 출력하시오

입력 : 6000

출력 :

- 1000 1000 1000 1000 1000 1000

- 5000 1000

 

=> 순서가 중요하지 않고, 중복을 허용하므로 "중복조합"이다. 

#include <stdio.h>

int sumBalls(int *balls, int ballSize){
    int i, sum = 0;
    for(i=0; i<ballSize; i++){
        sum += balls[i];
    }
    return sum;
}

void func(int input, int *bucket, int bucketSize, int k, int *balls, int ballSize){
    int i, j;
    
    int sum_balls;
    sum_balls = sumBalls(balls, ballSize);
    
    if(sum_balls == input){
        for(j=0; j<ballSize; j++){
            printf("%d ", balls[j]);
        }
        printf("\n");
        return;
    } else if(sum_balls > input){
        return;
    }
    
    for(i=k; i<bucketSize; i++){
        balls[ballSize] = bucket[i];
        func(input, bucket, bucketSize, i, balls, ballSize+1);
    }
    
}

int main(void) {
    
    int moneys[3] = {1000,5000,10000};
    int answer[1000];
    int input;
    
    scanf("%d", &input);
    
    func(input, moneys, 3, 0,  answer, 0);
    
    return 0;
}

 

 

 

 

 

 

 

 

 

반응형

+ Recent posts