Description:

这一关兔小灰需要将一根长的木棒切成N段。每段的长度分别为L1,L2,…,LN(1 <= L1,L2,…,LN <= 1000,且均为整数)个长度单位。我们认为切割时仅在整数点处切且没有木材损失。
然而兔小灰发现,每一次切割花费的体力与该木棒的长度成正比,不妨设切割长度为1的木棒花费1单位体力。例如:若N=3,L1 = 3,L2 = 4,L3 = 5,则木棒原长为12,木匠可以有多种切法,如:先将12切成3+9.,花费12体力,再将9切成4+5,花费9体力,一共花费21体力;还可以先将12切成4+8,花费12体力,再将8切成3+5,花费8体力,一共花费20体力。显然,后者比前者更省体力。那么,兔小灰至少要花费多少体力才能完成切割任务呢?

Input:

第1行:1个整数N(2 <= N <= 500)第2 - N + 1行:每行1个整数Li(1 <= Li <= 1000)。

Output:

输出最小的体力消耗。

Sample Input:

3
3
4
5

Sample Output:

19

题目链接

这道题目先分析样例,花费最少体力的切法是先将12切成5+7,花费12体力,再将7切成3+4,花费7体力,一共花费19体力。因为每次切木棒所花费的额体力都是切的目标木棒的长度,所以在一根木棒长度一定的情况下优先切去长的部分,剩下的木棒就会越短,后面切木棒的时候花费的体力就会越小。但是样例只有3段,如果是四段以上的话按照这种做法就会出错,因为有可能将一根木棒切为两部分然后将两部分再分别切做法最优而不是将一根木棒切为两部分,一部分是目标木棒中最长的一个,另一部分继续切。这时可以将问题反过来看,将所有目标木棒拼接为一整根木棒所花费的最小体力值(拼接两根木棒所花费的体力值为两根木棒长度之和),继续分析样例先将3+4,花费7体力,再将7+5,花费12体力,一共花费19体力。这样思路就很清晰了,先拼接长度最短的木棒,拼接后将拼接好的木棒再加入到比较队列之中,继续选取长度最小的两个木棒拼接。这里因为一直有新元素加入所以需要不断对目标队列进行排序,这里用优先队列就可以自动对目标队列进行排序。优先队列详解

C++STL——优先队列

优先队列还可以优化Dijkstra算法

HDU 2544 最短路(最短路径)

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const int maxn = 510;
const double eps = 1e-5;
const double pi = asin(1.0) * 2;
const double e = 2.718281828459;

struct cmp {
    bool operator() (const int &i, const int &j) {
        return i > j;
    }
};

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    priority_queue<int, vector<int>, cmp > q;
    int n, res = 0;
    cin >> n;
    for (int i = 0; i < n; ++i) {
        int a;
        cin >> a;
        q.push(a);
    }
    while (n > 1) {
        int a = q.top();
        q.pop();
        int b = q.top();
        q.pop();
        res += a + b;
        q.push(a + b);
        n--;
    }
    cout << res;
    return 0;
}