N과 m (2)

[Silver III] N과 M (2) - 15650

문제 링크

성능 요약

메모리: 1116 KB, 시간: 0 ms

분류

백트래킹

제출 일자

2023년 12월 31일 20:46:53

문제 설명

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

  • 1부터 N까지 자연수 중에서 중복 없이 M개를 고른 수열
  • 고른 수열은 오름차순이어야 한다.

입력

첫째 줄에 자연수 N과 M이 주어진다. (1 ≤ M ≤ N ≤ 8)

출력

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

수열은 사전 순으로 증가하는 순서로 출력해야 한다.

TIL

  • 가지치기의 조건만 잘 설정해두면 무리없이 구현했다.

BackTracing

  1. 확장
  2. 가지치기
  3. 끝까지 간뒤에 다시 올라오기 (이때 원상태로 복원시키면서)

Feedback

  • M과 N 시리즈의 1번 문제를 조금 응용하면 쉽게 풀 수 있었다.
    가지치기만 신경써서 구현하면 될 듯

내 코드

#include <stdio.h>
#include <stdbool.h>
#define SIZE 9
void combination(int arr[],bool isVisted[],int N,int M,int depth);
int main(){

    int N,M;
    scanf("%d %d",&N,&M);
    int arr[SIZE]={0};
    bool isVisted[SIZE]={0};

    combination(arr,isVisted,N,M,0);


    return 0;
}


//arr[depth] 추가하는 함수
void combination(int arr[],bool isVisted[],int N,int M,int depth){
    //종료 조건 : depth가 M이면 arr는 다 찼음. 출력
    if(depth==M){
        for(int i=0;i<M;i++){
            printf("%d ",arr[i]);
        }
        printf("\n");
        return;
    }
    //방문
    //확장
    for(size_t i=1;i<=N;i++){
        //가지치기
        bool flag=true; // 숫자 i를 탐색하는게 맞는 것인가?
        for(size_t j=i;j<=N;j++){
            if(isVisted[j]) flag=false;
        }
        if(flag){
            isVisted[i]=true;
            arr[depth]=i;
            //재귀
            combination(arr,isVisted,N,M,depth+1);
            //올라오면서 원상태로 되돌리기
            isVisted[i]=false;
        }
    }
}

Categories:

Updated:

Leave a comment