Notice
Recent Posts
Link
«   2025/01   »
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
Archives
관리 메뉴

이우의 개발일지

[백준 / C++] 15663번 N과 M (9) - (1), 백트래킹 본문

Coding

[백준 / C++] 15663번 N과 M (9) - (1), 백트래킹

공대이우 2025. 1. 15. 11:30
반응형

백준 15663번 N과 M (9) 문제 

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

 

문제

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

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

입력

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

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

출력

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

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

예제 입력 1 

3 1
4 4 2

예제 출력 1 

2
4

예제 입력 2 

4 2
9 7 9 1

예제 출력 2 

1 7
1 9
7 1
7 9
9 1
9 7
9 9

 


 

15663 N과 M 코드 문제 풀이

 

이 문제는 이전 N과 M 문제와는 다르게 까다로운 조건이 추가되었다.

바로, 똑같은 수가 들어갈 수 있다는 것이다. 예제 입력 이번 처럼 4가지 숫자 중 9, 7, 9, 1 같이 같은 숫자가 중복해서 들어가는데 출력할 때는 9 1, 9 7, 9 9 같이 중복되는 배열이 똑같이 나오면 안된다. 

 

따라서, 여기서 중요한 조건이 추가되어야한다. 

나는 Lastpick 변수를 이용해서 사용한 값을 기억해놓고, 다음 반복문에 들어갔을 때 그 값이 만약 중복이면 continue를 통해 다음 반복문으로 넘어가게 만들었다. 

 

void back(int check) {
	
	if (check == m) {
		for (int i = 1; i <= m; i++) {
			cout << now[i] << " ";
		}
		cout << '\n';
		return;
	}
	int lastpicked = -1;

	for (int i = 0; i < n; i++) {
		if (issued[i]) continue;
		if (lastpicked == num[i]) continue;

		now[check + 1] = num[i];
		issued[i] = 1;
		lastpicked = num[i];
		back(check + 1);
		issued[i] = 0;
		
	}

	return;
}

 

이렇게 할 시에 예제 입력 2번을 예로 들면, 1 7 -> 1 9 -> 1 9 가 나올 타이밍에 pass를 하게 된다. 또한, 9 1 -> 9 7 -> 9 9 -> 9 1 가 나올 타이밍에 pass하게 된다. 따라서 모든 경우의 수는 출력하되 중복하는 경우는 막을 수 있게되는 조건이 추가되어 N과 M (9) 문제를 해결할 수 있다. 

 


N과 M (9) 전체 코드

 

#include <iostream>
#include <algorithm>


using namespace std;

int num[9] = { 0 };
bool issued[9];

int now[9];
int n, m;
void back(int check) {
	
	if (check == m) {
		for (int i = 1; i <= m; i++) {
			cout << now[i] << " ";
		}
		cout << '\n';
		return;
	}
	int lastpicked = -1;

	for (int i = 0; i < n; i++) {
		if (issued[i]) continue;
		if (lastpicked == num[i]) continue;

		now[check + 1] = num[i];
		issued[i] = 1;
		lastpicked = num[i];
		back(check + 1);
		issued[i] = 0;
		
	}

	return;
}


int main() {
	
	cin >> n >> m;

	for (int i = 0; i < n; i++) {
		cin >> num[i];
	}

	sort(num, num + n);

	int now;
	int past = num[0];
	int n_size = n;

	back(0);

	return 0;
}

반응형