[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;

}

  

你可能感兴趣的:(IO)