티스토리 뷰
문제 출처 : https://www.acmicpc.net/problem/1715
문제 해결에 필요한 알고리즘 : 그리디 알고리즘
해설
가장 작은 두 수끼리 계속 합쳐주는 것이 가장 최적이다. priority queue를 이용하여 문제를 해결 할 수 있다. 모든 수를 큐에 삽입한 후 가장 작은 두 수를 꺼내 연산한 뒤 결과를 다시 큐에 넣어주면 된다. 이렇게 큐에 한가지의 숫자가 남을 때 까지 하면 최소로 비교하는 횟수를 알 수 있다.
정당성 증명
S(A, b)를 A라는 수의 집합과 b라는 수를 포함하는 카드의 집합이라고 정의한다.
MIN(S) 는 수의 집합에서 가장 최적으로 비교하는 횟수라고 정의한다.
S(A, b), S(A, c)가 있을 때 b > c 라고 하면,
MIN(S(A, b)) > MIN(S(A, c)) 가 됨을 쉽게 알 수 있다.
가장 작은 두 수를 합치지 않았을 때는 무조건 손해를 보는 상황이 생긴다.
따라서 가장 작은 두 수를 합치는 것이 가장 최적임을 알 수 있다.
시간복잡도
큐에 값을 넣는데는 만큼 걸린다. 이 때 처음 삽입할 때
만큼 걸리게 된다. 또 큐에 있는 값을 pop하고 push하는데
만큼 걸린다. 또 N번 진행하므로
만큼 걸리게 된다.
따라서 시간복잡도는 이다.
카드 정렬하기 코드 [ C++ ]
#include <cstdio> #include <vector> #include <queue> struct cmp { bool operator() (int i, int j) { return i > j; } }; int main() { int n, res = 0; std::priority_queue < int, std::vector < int >, cmp > pq; scanf("%d", &n); for (int i = n; i--; ) { int m; scanf("%d", &m); pq.push(m); } for (; pq.size() > 1; ) { int t1 = pq.top(); pq.pop(); int t2 = pq.top(); pq.pop(); res += t1 + t2; pq.push(t1 + t2); } printf("%d", res); return 0; }
'프로그래밍 > 알고리즘' 카테고리의 다른 글
[BOJ_2243_RN] 사탕상자 Problem Solving (0) | 2018.12.08 |
---|---|
[BOJ_11066_RN] 파일 합치기 Problem Solving (3) | 2018.11.01 |
[BOJ_11652_RN] 카드 Problem Solving (1) | 2018.10.30 |
[BOJ_2156_RN] 포도주 시식 Problem Solving (0) | 2018.10.19 |
[BOJ_9084_RN] 동전 Problem Solving (0) | 2018.10.15 |
댓글