[wikioi]合并果子

http://wikioi.com/problem/1063/

这题是贪心+堆。主要想练习一下堆的写法。算法导论里的方法名是heapify()等,但大家经常用更直观的down(), up()方法(向上,下调整),根据这两个方法,可以有build,insert,getmin方法。

向下调整的代码稍微需要判断一下左右子树是否越界,其他都很简单。

#include <iostream>
using namespace std;
#define LEN 10005
int num[LEN];
int size;

void swap(int a, int b) {
    int tmp = num[a];
    num[a] = num[b];
    num[b] = tmp;
}

void down(int i) {
    if (i > size) return;
    int left = i * 2;
    int right = i * 2 + 1;
    int minIdx = left;
    if (right <= size && num[left] > num[right]) {
        minIdx = right;
    }
    if (left > size || num[i] <= num[minIdx])
        return;
    else {
        swap(i, minIdx);
        down(minIdx);
    }
}

void up(int i) {
    if (i == 1) return;
    if (num[i / 2] > num[i]) {
        swap(i / 2, i);
        up(i / 2);
    }
}

void build() {
    for (int i = size / 2; i >= 1; i--) {
        down(i);
    }
}

int getmin() {
    swap(1, size);
    size--;
    down(1);
    return num[size + 1];
}

void insert(int x) {
    size++;
    num[size] = x;
    up(size);
}

int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> num[i];
    }
    size = n;
    build();
    int sum = 0;
    while (size > 1) {
        int a = getmin();
        int b = getmin();
        sum += a + b;
        insert(a + b);
    }
    cout << sum << endl;
}

  

posted @ 2013-11-10 22:46  阿牧遥  阅读(260)  评论(0编辑  收藏  举报