例子:

问题:搬水果


题目描述


        在一个果园里,小明已经将所有的水果打了下来,并按水果的不同种类分成了若干堆,小明决定把所有的水果合成一堆。每一次合并,小明可以把两堆水果合并到一起,消耗的体力等于两堆水果的重量之和。当然经过 n‐1 次合并之后,就变成一堆了。小明在合并水果时总共消耗的体力等于每次合并所耗体力之和。

       假定每个水果重量都为 1,并且已知水果的种类数和每种水果的数目,你的任务是设计出合并的次序方案,使小明耗费的体力最少,并输出这个最小的体力耗费值。例如有 3 种水果,数目依次为 1,2,9。可以先将 1,2 堆合并,新堆数目为3,耗费体力为 3。然后将新堆与原先的第三堆合并得到新的堆,耗费体力为 12。所以小明总共耗费体力=3+12=15,可以证明 15 为最小的体力耗费值。


输入格式

每组数据输入包括两行,第一行是一个整数 n(1<=n<=10000),表示水果的种类数,如果 n 等于 0 表示输入结束,且不用处理。第二行包含 n 个整数,用空格分隔,第 i 个整数(1<=ai<=1000)是第 i 种水果的数目。

输出

对于每组输入,输出一个整数并换行,这个值也就是最小的体力耗费值。输入数据保证这个值小于 2^31。

样例输入

3

42 708 119

4

749 522 629 823

6

55 323 489 378 618 194

0

样例输出

1030

5446

4935


详解priority_queue类

priority_queue调用 STL里面的 make_heap(), pop_heap(), push_heap() 算法实现,也算是堆的另外一种形式。先写一个用 STL 里面堆算法实现的与真正的STL里面的 priority_queue用法相似的priority_queue, 以加深对 priority_queue 的理解


#include <iostream>

#include <algorithm>

#include <vector>

 

using namespace std;

 

class priority_queue

{

    private:

        vector<int> data;

         

    public:

        void push( int t ){ 

            data.push_back(t); 

            push_heap( data.begin(), data.end()); 

        }

         

        void pop(){

            pop_heap( data.begin(), data.end() );

            data.pop_back();

        }

         

        int top() { return data.front(); }

        int size() { return data.size(); }

        bool empty() { return data.empty(); }

};

 

 

int main()

{

    priority_queue test;

    test.push( 3 );

    test.push( 5 );

    test.push( 2 );

    test.push( 4 );

     

    while( !test.empty() ){

        cout << test.top() << endl;

        test.pop(); }

         

    return 0;

 

}

 

STL里面的 priority_queue 写法与此相似,只是增加了模板及相关的迭代器什么的。 


priority_queue 对于基本类型的使用方法相对简单。他的模板声明带有三个参数:

priority_queue<Type, Container, Functional>

其中Type 为数据类型, Container 为保存数据的容器,Functional 为元素比较方式。

Container 必须是用数组实现的容器,比如 vector, deque 但不能用 list.

STL里面默认用的是 vector. 比较方式默认用 operator< , 所以如果你把后面俩个参数缺省的话,

优先队列就是大顶堆,队头元素最大。

 

#include <iostream>

#include <queue>

 

using namespace std;

 

int main(){

    priority_queue<int> q;

     

    for( int i= 0; i< 10; ++i ) q.push( rand() );

    while( !q.empty() ){

        cout << q.top() << endl;

        q.pop();

    }

     

    getchar();

    return 0;

}

 

如果要用到小顶堆,则一般要把模板的三个参数都带进去。

STL里面定义了一个仿函数 greater<>,对于基本类型可以用这个仿函数声明小顶堆

 

#include <iostream>

#include <queue>

#include <functional>                                //greater<>在头文件functional中定义

 

using namespace std;

 

int main(){

    priority_queue<int, vector<int>, greater<int> > q;

     

    for( int i= 0; i< 10; ++i ) q.push( rand() );

    while( !q.empty() ){

        cout << q.top() << endl;

        q.pop();

    }

     

    getchar();

    return 0;

}

 


对于自定义类型,则必须自己重载 operator< 或者自己写仿函数

 

#include <iostream>

#include <queue>

 

using namespace std;

 

struct Node{

    int x, y;

    Node( int a= 0, int b= 0 ):

        x(a), y(b) {}

};

 

bool operator<( Node a, Node b ){

    if( a.x== b.x ) return a.y> b.y;

    return a.x> b.x; 

}

 

int main(){

    priority_queue<Node> q;

     

    for( int i= 0; i< 10; ++i )

    q.push( Node( rand(), rand() ) );

     

    while( !q.empty() ){

        cout << q.top().x << ' ' << q.top().y << endl;

        q.pop();

    }

     

    getchar();

    return 0;

}

自定义类型重载 operator< 后,声明对象时就可以只带一个模板参数。

但此时不能像基本类型这样声明

priority_queue<Node, vector<Node>, greater<Node> >;

原因是 greater<Node> 没有定义,如果想用这种方法定义则可以按如下方式:

 

#include <iostream>

#include <queue>

 

using namespace std;

 

struct Node{

    int x, y;

    Node( int a= 0, int b= 0 ):

        x(a), y(b) {}

};

 

struct cmp{

    bool operator() ( Node a, Node b ){

        if( a.x== b.x ) return a.y> b.y;

         

        return a.x> b.x; }

};

 

int main(){

    priority_queue<Node, vector<Node>, cmp> q;

     

    for( int i= 0; i< 10; ++i )

    q.push( Node( rand(), rand() ) );

     

    while( !q.empty() ){

        cout << q.top().x << ' ' << q.top().y << endl;

        q.pop();

    }

     

    getchar();

    return 0;

 

 

//以上代码实现的是一个小顶堆



问题解决(我的源代码,代码格式复制上来就这样,请谅解.):

#include <iostream>

#include <queue>

#include <vector>

#include <functional>

using namespace std;


int main()

{


int n;

cin >> n;

while(n!=0)

{

int i;

priority_queue<int,vector<int>,greater<int> >q;


for(i = 0; i < n; i++)

{

int temp;

cin >> temp;

q.push(temp);

}

int result = 0;


while(q.size() > 1)

{

int a = q.top();

q.pop();

int b = q.top();

q.pop();

result += a+b;

q.push(a+b);

}


cout << result << endl;


n = 0;

cin >> n;

}


return 0;

}




LOFTER:hgfalgorithm   http://hgfal.lofter.com/post/28eef2_f96f41