본문 바로가기
알고리즘/백준[분발!]

[백준 1722] 순열의 순서

by RoJae 2019. 3. 17.


문제 : https://www.acmicpc.net/problem/1722


문제를 처음에 보고 너무 쉽게 생각했는지, 직접 구현한 배열의 next_permutation을 사용했다.

하지만, 시간초과... next_permutation으로 문제를 풀면 Big-O 표기로

O(N!)이 나오기 때문이였다.


항상 분발하는 자세로 겸손히 공부해야겠다. ㅠㅠ


실패한 코드

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include<iostream>
#include<algorithm>
 
using namespace std;
 
bool next_permutation(int *a, int n){
    int i = n-1;                    // 뒤부터 시작 
    while(i > 0 && a[i] <= a[i-1])    // 어디까지가 감소수열인가?? 
        i -= 1;
    if(i <= 0)                        // 전체가 감소수열이다. 
        return false;                // 다음 수열은 존재하지 않는다.
    int j = n-1;
    while(a[i-1>= a[j])
        j -= 1;
    swap(a[i-1],a[j]);
    j = n - 1;
    while(i < j){
        swap(a[i],a[j]);
        i +=1;
        j -=1;
    }
    return true;
}
void problem1(int *a, int m, int size){
    for(int i = 0; i < size; i++)
        a[i] = i+1;
        
    for(int i = 0; i < m-1; i++)
        next_permutation(a,size);
    
    for(int i = 0; i < size; i++)
        cout << a[i] << ' ';
    cout << '\n';
    
    return;    
}
void problem2(int *a, int size){
    int *= new int[size];
    int cnt = 1;
    
    for(int i = 0; i < size; i++)
        b[i] = i+1;
        
    while(1){
        for(int i = 0; i < size; i++){
            if(b[i] != a[i])
                break;
            else if(i == size-1){
                cout << cnt;
                return;
            }
        }
        cnt++;
        next_permutation(b,size);
    }
}
int main(){
    int n;
    int p;
    cin >> n >> p;
    
    int *arr = new int[n];
    
    if(p == 1){
        int next;
        cin >> next;
        problem1(arr,next,n);
    }
    else if(p == 2){
        for(int i = 0; i < n; i++)
            cin >> arr[i];
        problem2(arr,n);
    }
    return 0;
}
cs

구글 검색결과, 팩토리얼을 사용하는 방법이 있었는데


해결법


입력 : 4 1 3

 => 4개의 원소를 가진 순열의 3번째 집합을 구하라


1 2 3 4

1 2 4 3

1 3 2 4

식으로 하나씩 구하면, O(N!)이 뜬다.

반성한다. ㅠㅠㅠ


int SUM = 0, K = 3;        // 지금까지 경우의 수 SUM, 입력된 사전 순 K

이때 1 X X X가 가질 수 있는 경우의 수는 6가지로, 입력 K에 포함하지 않는다.

(K > 3!)?

FALSE 이기 때문에, 첫 번째 원소는 1이다.


마찬가지로 1 2 X X도 적용하면, (사용하지 않은 가장 작은 수 2)

(K > 2!)?

TRUE 이기 때문에, 다음으로 큰 수를 선택한다.

( 이때 SUM += 2!)


1 3 X X는 입력 범위(K=3)에 포함이 될까?

(K > 2*2!)? 

FALSE로 포함되지 않는다, 1 3 X X가 된다.


다시 한번 1 3 X X에서 1 3 2 X가 포함되는지 확인하겠다.

1 3 2 X를 포함하는가?

(K > SUM + 1!)?    (K = 3)

FALSE로 포함하지 않는다.


1 3 2 X => X는 남는 수로 결정

1 3 2 4가 되는 것이다.



※ 본 글은 개인 포트폴리오 혹은 공부용으로 사용하기 때문에, 무단 복사 유포는 금지하지만, 개인 공부 용도로는 얼마든지 사용하셔도 좋습니다.

반응형

'알고리즘 > 백준[분발!]' 카테고리의 다른 글

[백준 2261] 가장 가까운 두 점  (0) 2019.04.02

댓글