[순열] 백준 : 다음 순열, 이전 순열, 모든 순열
2021. 7. 3. 04:41ㆍ알고리즘 관련/완전 탐색
다음 순열 : https://www.acmicpc.net/problem/10972
이전 순열 : https://www.acmicpc.net/problem/10973
모든 순열 : https://www.acmicpc.net/problem/10974
다음 순열과 이전 순열에선 우선 input으로 어떤 수열이 주어진다.그러면 결과로 그 수열 이후/이전에 오는 순열(permutation)을 프린트한다.
모든 순열에선 n이 주어지며, 1 ~ n 까지 모든 permutation을 구하면 된다.
1. 반복문으로 해결하기 - 다음 순열
next_permutation이 치트키이지만... 안쓰고 반복문으로 도전해보았다.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int N, k;
void printNum(vector<int> nums)
{
for (auto num : nums)
cout << num << ' ';
cout << '\n';
}
int main(void)
{
cin >> N;
vector<int> numbers;
for (int i = 0; N > i; i++)
{
cin >> k;
numbers.push_back(k);
}
if (N == 1)
{
cout << -1 << '\n';
return 0;
}
int lastNum = N - 1; // i의 바로 오른쪽에 있는 숫자.
for (int i = N - 1; i >= 0; i--) // 맨 오른쪽에서부터 왼쪽으로 탐색을 시작한다.
{
if (numbers[lastNum] > numbers[i]) // 오른쪽에서 왼쪽으로 탐색을 하다가, 숫자가 감소하는 지점에 도달시
{
int nextIdx = N - 1;
for (; numbers[nextIdx] < numbers[i]; nextIdx--) // numbers[i]의 오른쪽에서, numbers[i] 보다 더 큰 첫번째 수를 찾음
;
iter_swap(numbers.begin() + i, numbers.begin() + nextIdx); // 그리고 그 수를 numbers[i] 와 스왑.
sort(numbers.begin() + lastNum, numbers.end()); // i의 바로 오른쪽에 있는 숫자부터 끝까지 오름차순 정렬.
printNum(numbers);
return 0;
}
if (numbers[lastNum] <= numbers[i]) lastNum = i; // 오른쪽에서 왼쪽으로 갈수록 숫자가 증가하면, lastNum을 한칸씩 왼쪽으로 옮김.
}
cout << -1 << '\n';
return 0;
}
아이디어는 다음과 같다.
주어진 순열의 오른쪽에서부터 왼쪽으로 탐색하는데, 숫자가 커지면 패스하고 작아지는 지점에서 멈춘다. 그리고 그 지점까지, 지점보다 큰 첫번째 수를 찾아 지점과 스왑한다. 이후, 원래 지점의 자리 바로 오른쪽에서부터 끝까지 오름차순 정렬을 하면 끝!
(쉽지만은 않았다..ㅎㅎㅎ)
2. next_permutation, prev_permutation 을 사용하여 해결하기 - 이전 순열
치트키를 써보았다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(void)
{
int N, k;
vector<int> nums;
cin >> N;
for (int i = 0; N > i; i++)
{
cin >> k;
nums.push_back(k);
}
if (prev_permutation(nums.begin(), nums.end()))
{
for (auto num : nums)
cout << num << ' ';
cout << '\n';
return 0;
}
cout << -1 << '\n';
return 0;
}
코드가 훨씬 깔끔하고 직관적이다!
next_permutation과 prev_permutation은 다음/이전 순열 생성시 true을 반환한다. 생성에 실패할 경우 false를 반환한다. next_permutation/prev_permutation 함수 호출시, nums는 다음/이전 순열로 바뀐다.
3. 모든 순열
기본적인 순열 생성 문제.
#include <iostream>
#include <vector>
using namespace std;
int N, numStatus[8] = {0};
void permutation(vector<int> nums)
{
if (nums.size() == N)
{
for (auto num : nums)
cout << num << ' ';
cout << '\n';
return;
}
for (int i = 0; N > i; i++)
{
if (numStatus[i])
continue;
nums.push_back(i + 1);
numStatus[i] = 1;
permutation(nums);
nums.pop_back();
numStatus[i] = 0;
}
}
int main(void)
{
cin >> N;
vector<int> nums;
permutation(nums);
return 0;
}
'알고리즘 관련 > 완전 탐색' 카테고리의 다른 글
[백준] 스도쿠 (0) | 2021.08.24 |
---|---|
[문제 유형]완전 탐색 유형 (0) | 2021.07.04 |
[순열] 백준 : N과 M - 2, 4, 6, 8, 10, 12 (조합) (0) | 2021.07.02 |
[순열] 백준 : N과 M - 1, 3, 5, 7, 9, 11 (순열) (0) | 2021.07.02 |
[재귀] 백준: 1, 2, 3 더하기 (0) | 2021.06.28 |