木板切割

题目描述

描述 Description
FarmerJohn想修理牧场栅栏的某些小段。为此,他需要N(1<=N<=20,000)块特定长度的木板,第i块木板的长度为Li(1<=Li<=50,000)。然后,FJ去买了一块很长的木板,它的长度正好等于所有需要的木板的长度和。接下来的工作,当然是把它锯成需要的长度。FJ忽略所有切割时的损失——你也应当忽略它。
FJ郁闷地发现,他并没有锯子来把这块长木板锯开。于是他把这块长木板带到了Farmer Don的农场,想向FD借用锯子。
作为一个有商业头脑的资本家,FarmerDon没有把锯子借给FJ,而是决定帮FJ锯好所有木板,当然FJ得为此付出一笔钱。锯开一块木板的费用,正比于木板的长度。如果这块木板的长度是21,那么锯开它的花费便是21美分。
谈妥条件后,FD让FJ决定切割木板的顺序,以及每次切割的位置。请你帮FJ写一个程序,计算为了锯出他想要的木板,他最少要花多少钱。很显然,按不同的切割顺序来切开木板,FJ的总花费可能不同,因为不同的切割顺序,会产生不同的中间结果。
输入格式 Input Format
* 第1行: 一个正整数N,表示FJ需要木板的总数
* 第2…N+1行: 每行包含一个整数,为FJ需要的某块木板的长度
输出格式 Output Format
* 第1行: 输出一个整数,即FJ完成对木板的N-1次切割的最小花费

题解

emm 这道题和合并果子一模一样。

  • 可以用优先队列写
  • 维护小根堆也可以

code(小根堆)

#include 
using namespace std;
const int maxn = 2e4 + 100;
typedef long long LL;

LL x, sum, n;

template <typename T>
inline void read(T &s) {
    s = 0;
    T w = 1, ch = getchar();
    while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }
    while (isdigit(ch))  { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }
    s *= w;
}

namespace MakeHeap {
    LL size;
    LL heap[maxn];

    inline void swap(LL &aa, LL &bb) { aa ^= bb ^= aa ^= bb; }

    inline void up(LL p) {
        while (p > 1) {
            if (heap[p] < heap[p / 2]) {
                swap(heap[p], heap[p / 2]);
                p /= 2;
            }
            else break;
        }
    }

    inline void insert(LL val) {
        heap[++size] = val;
        up(size);
    }

    inline LL GetTop() { return heap[1]; }

    inline void down(LL p) {
        LL s = p * 2;
        while (s <= size) {
            if (s < size && heap[s] > heap[s + 1]) s++;
            if (heap[s] < heap[p]) {
                swap(heap[s], heap[p]);
                p = s, s = p * 2;
            }
            else break;
        }
    }

    inline void Extract() { 
        heap[1] = heap[size--];
        down(1);
    }
}
using namespace MakeHeap;

int main() {
    read(n);
    for (int i = 1; i <= n; ++i) {
        read(x); insert(x);
    }
    sum = 0;
    while (size > 1) {
        LL x1 = GetTop();
        Extract();
        LL x2 = GetTop();
        Extract();
        sum += (x1 + x2);
        insert(x1 + x2);
    }
    printf("%lld\n", sum);
    return 0;
}

你可能感兴趣的:(题解————题解,数据结构——数据结构,数据结构——二叉堆,模板——模板)