코딩테스트

[백준] N과 M (1) c++ (15649번)

코딩너구리 2025. 6. 28. 14:48

N과 M (1)

 
시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초 512 MB 137824 88779 55504 63.373%

문제

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

  • 1부터 N까지 자연수 중에서 중복 없이 M개를 고른 수열

입력

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

출력

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

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


문제 해결 과정

백트랙킹을 활용해 문제를 풀어야 하는 단순예제이다. 다만 이 알고리즘 자체가 DPS 재귀를 이용해야 하기 때문에

로직 자체가 이해하기 쉽진 않다. 나도 여러번 보고, 물어보면서 조금 이해할 수 있었다. 백트랙킹에 관련된 더 다양한 문제들을 풀어봐야 겠다는 생각이 들었다.

 

#include <iostream>

using namespace std;

int N, M;

int arr[10];
bool visited[10];

//depth는 깊이. (x,y) 에서 y를 담당한다.
void BackTracking(int depth)
{
	//depth가 = M 인경우는 y값이 끝까지 도달했을때 이제 그 한줄을 출력한다.
	if (depth == M)
	{
		for (int i = 0; i < M; i++)
		{
			cout << arr[i] << " ";
		}

		cout << "\n";

		return;
	}
	else
	{
		//백트랙킹 핵심 부분 X의 값을 기준으로 반복을 돌린다
		for (int i = 1; i <= N; i++)
		{
			//사용된 수가 아닐때를 탐색
			if (false == visited[i])
			{
				//방문여부를 갱신하고
				visited[i] = true;

				//현재 선택된 값을 지정
				arr[depth] = i;

				//재귀를 통해서 다음 수를 계산.
				BackTracking(depth + 1);

				//재귀를 빠져나오면 방문여부를 초기화
				visited[i] = false;
			}
		}
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	cin >> N >> M;
	BackTracking(0);
}

https://www.acmicpc.net/problem/15649