출처 : https://www.acmicpc.net/problem/6443
정답 : https://github.com/stemp12/study/blob/master/acmicpc.net/2016.02/6443.cpp
그냥 순열놀이이다. 그렇게 어렵지 않은 문제이다.
입력을 먼저 정렬시키고 순열놀이로 쭉 뽑아내면 된다. 다만, 중복이 있으면 안되는데, 이 부분만 처리해주면된다.
다만 조금 의아한부분이 있다면 내가 직접 구현한 DFS로는 시간초과가 났다. 그래서 STL의 next_permutation()을 사용하니 정답이 나왔다. 내가 만든 DFS에 소모적인 부분이 많다는 말인데... 이건 분명 개선해야할 부분이다.
비록 STL로 정답을 맞았을지언정 현재 내가만드는 DFS에는 낭비 되는 부분이 존재하기에 STL에 있는 next_puermutation의 구조를 분석해봤다.
http://en.cppreference.com/w/cpp/algorithm/next_permutation
이 사이트를 참조하면 내부 구조에 대해서 알 수있다.
나는 기본적으로 해당 문자를 사용했는지 안했는지 체크하는 방식으로 DFS를 구성하였다. 그러다보니 동일한 문자일경우 나의 DFS는 알 수 없으므로, 중복이 반드시 생긴다. 아마 이 문제 때문에 시간초과가 발생한듯 하다.
물론 출력을 제어하기 위해서 맵이나 다른 방법을 통해 기존에 만든 것들을 저장시키고 확인하여 중복을 피할 수 있으나, 어찌 되었든 중복이 발생하기 때문에, 비효율적이라고 볼 수있다.
추후 이런 문제를 피하기 위하여 새로운 DFS방법을 습득할 필요를 느껴 더 공부해봤다.
templatebool next_permutation(BidirIt first, BidirIt last) { if (first == last) return false; BidirIt i = last; if (first == --i) return false; while (true) { BidirIt i1, i2; i1 = i; if (*--i < *i1) { i2 = last; while (!(*i < *--i2)) ; std::iter_swap(i, i2); std::reverse(i1, last); return true; } if (i == first) { std::reverse(first, last); return false; } } }
위의 방법이 STL에 있는 next_permutation인데, 좀 독특한 방법이라고 생각이 들었다. 확실히 내가 기본적으로 구성하는 방법과는 전혀 다른 방법이었다. 독특한 점은 재귀가 없다는 점이다. 단순히 반복문을 통해서 재귀와 동일한 능력을 만들고있다.
역시 STL은 정말 대단한 것이다.
'Algorithm' 카테고리의 다른 글
[AC] 2240 자두나무 (0) | 2016.02.24 |
---|---|
[AC] 1811 알약 (0) | 2016.02.24 |
[AC] 1535 안녕 (0) | 2016.02.24 |
[AC] 1793 타일링 (0) | 2016.02.24 |
[AC] 11729 하노이 탑 이동 순서 (0) | 2016.02.24 |