Processing math: 100%

2016년 8월 23일 화요일

1715 - 카드 정렬하기

https://www.acmicpc.net/problem/1715

항상 카드의 장수가 가장 작은 두 묶음을 합치는 것이 결과적으로 최소의 비교 횟수이다.
대체 왜..?
라고 생각할수있다. "왠지 그러는 게 맞는 것 같다"는 말도 안되는 논리(혹은 풀이 도출)로 풀어온 문제가 정말 많았다.
그래서 오늘은 증명을 연습해보려 한다.

카드를 합치는 과정을 설명하기 위해 다음과 같이 정의해보겠다.
a= 가장 작은 수 (i.e. a장의 카드 묶음)
b= 두번째로 작은 수
c=a,b 가 아닌 다른 어떤 수

위 정의에 의하면 abc 이다. 아래 3가지 경우가 있다.

  • ac를 합친 후, 그것을 b와 합친다 : (a+c)+{(a+c)+b}
  • ab를 합친 후, 그것을 c와 합친다 : (a+b)+{(a+b)+c}
  • bc를 합친 후, 그것을 a와 합친다 : (b+c)+{(b+c)+a}

세 항 모두 중괄호로 둘러싼 부분이 a+b+c로 공통이므로 비교하기 위해 생략할 수 있다.

a+ba+c 이고, a+bb+c 이므로
(a+b)+{(a+b)+c} 가 가장 최소이다.

따라서 가장 작은 두 수를 합치는 것이 항상 최소이다.

증명을 별로 해본적이 없어서 맞는 지 확신이 안 선다.
댓글로 지적해주시면 감사하겠습니다.


#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;

int main(){
    int t, N;
    scanf("%d", &N);
    priority_queue<int> q;
    while(N--){
        scanf("%d",&t);
        q.push(-t);
    }
    int r = 0;
    while(q.size()>1){
        int a=0, b=0;
        a = -q.top(); q.pop();
        b = -q.top(); q.pop();
        r += a+b;
        q.push(-a-b);
    }
    printf("%d", r);
    return 0;
}

댓글 1개:

ㅇㅇ :

a, b, c 가 낱개 파일이 아닌 이미 합쳐서 만든 파일의 경우, 파일을 합치기까지의 비용 역시 고려해야하지 않을까 생각합니다.

게시글 목록