baekjoon
[백준] 15663 N과M (9)
윤만석
2023. 6. 9. 13:42
문제
N개의 자연수와 자연수 M이 주어졌을 때, 아래 조건을 만족하는 길이가 M인 수열을 모두 구하는 프로그램을 작성하시오.
- N개의 자연수 중에서 M개를 고른 수열
입력
첫째 줄에 N과 M이 주어진다. (1 ≤ M ≤ N ≤ 8)
둘째 줄에 N개의 수가 주어진다. 입력으로 주어지는 수는 10,000보다 작거나 같은 자연수이다.
출력
한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다.
수열은 사전 순으로 증가하는 순서로 출력해야 한다.
숫자는 최대 N개이고, M길이의 수열을 만들어야합니다.
중복되는 수열을 제거해야하는데, 퀵소트의 시간복잡도는 NlogN이고, unique는 N입니다.
만들어진 수열의 최대 개수는 8! 즉 약 4만개이므로,, 통과하긴합니다.
백트래킹을 이용해서 주어진 숫자를 한번씩만 사용하는 순열을 만들고,
정렬하고 중복 수열을 삭제합니다.
#include<bits/stdc++.h>
#define FAST ios_base::sync_with_stdio(false),cin.tie(NULL);
#define mset(v) memset(v,0,sizeof(v));
#define rep(i,a) for(int i=0;i<a;++i)
#define REP(i,a) for(int i=1;i<=a;++i)
using namespace std;
typedef long long ll;
typedef pair<int, int> pi;
typedef tuple<int, int, int>ti;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
int dy[] = { -1,0,1,0 }, dx[] = { 0,1,0,-1 }, INF = 987654321;
int v[100000000], N, M, u[10];
vi a;
vvi s;
void bt(int t) {
if (t == M) {
vi temp;
rep(i, M) {
temp.push_back(v[i]);
}
s.push_back(temp);
return;
}
rep(i, N) {
if (!u[i]) {
v[t] = a[i];
u[i] = 1;
bt(t + 1);
u[i] = 0;
}
}
}
int main() {
FAST;
cin >> N >> M;
REP(i, N) {
int x;
cin >> x;
a.push_back(x);
}
sort(a.begin(), a.end());
bt(0);
sort(s.begin(), s.end());
s.erase(unique(s.begin(), s.end()), s.end());
for (auto r : s) {
for (int p : r) {
cout << p << " ";
}
cout << "\n";
}
}