알고리즘 풀이
10974. 모든 순열
남생이야
2024. 3. 1. 12:22
https://www.acmicpc.net/problem/10974
10974번: 모든 순열
N이 주어졌을 때, 1부터 N까지의 수로 이루어진 순열을 사전순으로 출력하는 프로그램을 작성하시오.
www.acmicpc.net
순열 알고리즘 문제이다. 브투트포스 알고리즘을 공부하면서 조합이나 순열관련된 문제들이 많이 나와서 이 둘을 다시 파헤치기 시작하게 되었다.
조합은 수식으로 nCr로 표현할 수 있는데 n개의 원소 중 r개를 뽑는 모든 경우를 살피는 것을 뜻한다.
수열은 수식으로 nPr로 표현할 수 있으며, n개의 원소 중 r개를 나열하는 모든 경우의 수를 뜻한다.
조합과 수열의 차이점은 for문의 시작 값이 조합은 현재 level의 값 수열은 해당 수의 시작값이다 문제에선 1로 시작했다.
그리고 수열은 나열하는 모든 경우의 수를 체크해야하는 체크 변수가 따로 존재한다. 조합은 어떤 순서든 해당 원소들이 중복이라면 하나로 치기때문에 그렇지 않다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int n;
bool visited[9];
void myPermu(int level, vector<int> result)
{
if (level == n)
{
for (int i = 0; i < level; i++)
{
cout << result[i] << ' ';
}
cout << '\n';
return;
}
// 순열이니까 1부터 시작 체크변수로 해당 값을 가져갔다고 체크해야한다
//조합과 다르게, 순열의 경우는 순서에 상관있게 선택해야 하므로 원소의 사용 여부를 나타내는 check 배열이 필요함.
for (int i = 1; i <= n; i++)
{
if (visited[i] == true) continue;
visited[i] = true; // 해당원소 사용햇으니 체크
result[level] = i; // 해당 인덱스 원소 선택
myPermu(level + 1, result); // 다음 for문으로 들어가는 역할 nPr은 r개의 포문을 중첩해서 만들어 검사하니 재귀함수로 일반화한다
visited[i] = false; // 해당원소 사용햇으니 초기화
}
}
int main() {
cin >> n;
vector<int> list;
for (int i = 0; i < n; i++)
{
list.push_back(i + 1);
}
myPermu(0, list);
return 0;
}