오늘도 N과 M 시리즈를 복습 차원에서 다시 풀어보았습니다. 유형마다 조금씩 차이도 있고, 함수 구현하는데 있어 도움이 많이 될 것 같아서 다시 풀어보았습니다.
6 ~ 12번 까지 문제 설명 드리겠습니다.
6번 : N개의 자연수 중에서 M개를 고른 수열, 고른 수열은 오름차순이어야 한다.
7번 : N개의 자연수 중에서 M개를 고른 수열, 같은 수를 여러 번 골라도 된다.(사전 순으로 증가하는 순서로 출력)
8번 : N개의 자연수 중에서 M개를 고른 수열, 같은 수를 여러 번 골라도 된다. 고른 수열은 비내림차순이어야 한다. 길이가 K인 수열 A가 A1 ≤ A2 ≤ ... ≤ AK-1 ≤ AK를 만족하면, 비내림차순이라고 한다.
9번 : N개의 자연수 중에서 M개를 고른 수열(중복 수열 제거, set 사용 or vector에서 중복원소 제거)
10번 : N개의 자연수 중에서 M개를 고른 수열, 고른 수열은 비내림차순이어야 한다.
11번 : N개의 자연수 중에서 M개를 고른 수열, 같은 수를 여러 번 골라도 된다.
12번 : N개의 자연수 중에서 M개를 고른 수열, 같은 수를 여러 번 골라도 된다. 고른 수열은 비내림차순이어야 한다.
<코드>
6번
#include <iostream>
#include <algorithm>
using namespace std;
int n, m;
bool check[9];
int num[9];
int result[9];
void print(int idx)
{
if (idx == m)
{
for (int i = 1; i < m; i++)
{
if (result[i] < result[i - 1])
return;
// 수열이 오름차순 정렬되어야 되기 때문에, 이전 인덱스 값이 더 크면 수열이 될 수 없다.
}
for (int i = 0; i < m; i++)
{
cout << result[i] << ' ';
}
cout << '\n';
return;
}
for (int i = 0; i < n; i++)
{
if (check[i])
continue;
check[i] = true;
result[idx] = num[i];
print(idx + 1);
check[i] = false;
}
}
int main()
{
cin >> n >> m;
for (int i = 0; i < n; i++)
{
cin >> num[i];
}
sort(num, num + n);
print(0);
}
7번
#include <iostream>
#include <algorithm>
using namespace std;
int n, m;
int num[8];
int result[8];
void print(int idx)
{
if (idx == m)
{
for (int i = 0; i < m; i++)
{
cout << result[i] << ' ';
}
cout << '\n';
return;
}
for (int i = 0; i < n; i++)
{
result[idx] = num[i];
print(idx + 1);
// 같은 수 중복 사용 가능하기에 boolean타입 check변수 불필요
}
}
int main()
{
cin >> n >> m;
for (int i = 0; i < n; i++)
{
cin >> num[i];
}
sort(num, num + n);
print(0);
}
8번
#include <iostream>
#include <algorithm>
using namespace std;
int n, m;
int num[9];
int result[9];
bool check[9];
void print(int idx, int start)
{
if (idx == m)
{
for (int i = 0; i < m; i++)
{
cout << result[i] << ' ';
}
cout << '\n';
return;
}
for (int i = start; i < n; i++)
{
result[idx] = num[i];
print(idx + 1, i);
//비내림차순 조건을 충족시키기 위해 매개변수 start를 두어 다음 인덱스에 이전 인덱스의 값이상이 들어오도록 설정
}
}
int main()
{
cin >> n >> m;
for (int i = 0; i < n; i++)
{
cin >> num[i];
}
sort(num, num + n);
print(0, 0);
}
9번
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
using namespace std;
int num[9];
int result[9];
bool check[9];
set<vector<int>> s;
vector<int> v;
vector<int>::iterator elem;
int n, m;
void print(int idx)
{
if (idx == m)
{
for (int i = 0; i < m; i++)
{
v.push_back(result[i]);
}
s.insert(v);
// 중복 원소 제거하기 위해 set헤더 이용
v.clear();
// 벡터에 새로운 값을 대입해야 하기 때문에 clear해주고 새롭게 시작
return;
}
for (int i = 0; i < n; i++)
{
if (!check[i])
{
check[i] = true;
result[idx] = num[i];
print(idx + 1);
check[i] = false;
}
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> n >> m;
for (int i = 0; i < n; i++)
{
cin >> num[i];
}
sort(num, num + n);
print(0);
for (auto v : s)
{
for (auto elem : v)
{
cout << elem << ' ';
}
cout << '\n';
}
}
10번
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
using namespace std;
int num[9];
int result[9];
bool check[9];
set<vector<int>> s;
vector<int> v;
vector<int>::iterator elem;
int n, m;
void print(int idx, int start)
{
if (idx == m)
{
for (int i = 0; i < m; i++)
{
v.push_back(result[i]);
}
s.insert(v);
v.clear();
return;
}
for (int i = start; i < n; i++)
{
if (!check[i])
{
check[i] = true;
result[idx] = num[i];
print(idx + 1, i);
check[i] = false;
}
// 비내림차순 조건을 충족
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> n >> m;
for (int i = 0; i < n; i++)
{
cin >> num[i];
}
sort(num, num + n);
print(0, 0);
for (auto v : s)
{
for (auto elem : v)
{
cout << elem << ' ';
}
cout << '\n';
}
}
11번
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
using namespace std;
int num[9];
int result[9];
bool check[9];
set<vector<int>> s;
vector<int> v;
vector<int>::iterator elem;
int n, m;
void print(int idx)
{
if (idx == m)
{
for (int i = 0; i < m; i++)
{
v.push_back(result[i]);
}
s.insert(v);
v.clear();
return;
}
for (int i = 0; i < n; i++)
{
result[idx] = num[i];
print(idx + 1);
//중복원소 허용하기에 check변수 불필요
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> n >> m;
for (int i = 0; i < n; i++)
{
cin >> num[i];
}
sort(num, num + n);
print(0);
for (auto v : s)
{
for (auto elem : v)
{
cout << elem << ' ';
}
cout << '\n';
}
}
12번
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
using namespace std;
int num[9];
int result[9];
bool check[9];
set<vector<int>>s;
vector<int>v;
vector<int>::iterator elem;
int n, m;
void print(int idx, int start)
{
if(idx == m)
{
for(int i=0;i<m;i++)
{
v.push_back(result[i]);
}
s.insert(v);
v.clear();
return;
}
int last = 0;
for(int i=start;i<n;i++)
{
if(last != num[i])
{
check[i] = true;
result[idx] = num[i];
last = num[i];
print(idx+1, i);
check[i] = false;
}
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin>>n>>m;
for(int i=0;i<n;i++)
{
cin>>num[i];
}
sort(num,num+n);
print(0, 0);
for(auto v : s)
{
for(auto elem : v) {
cout<<elem<<' ';
}
cout<<'\n';
}
}
질문 및 피드백 환영입니다. 저는 N과 M 시리즈에서 매개변수는 순열의 순서를 나타내는 idx와 비내림차순 조건을 충족시키기 위해 start를 두어 풀었습니다. 9번 문제부터는 set헤더를 이용해서 중복된 순열을 제거해주었습니다.
'PS > 백트래킹[Backtracking]' 카테고리의 다른 글
백준 N과 M (1) ~ (5) 복습 (2) | 2023.02.10 |
---|---|
백준 14500 테트로미노(c++) (0) | 2023.01.28 |
백준 6603 로또(c++) (0) | 2023.01.28 |
백트래킹(backtracking) (0) | 2022.08.10 |