堆(优先队列)-搬果子

    果园里面有n堆果子,每堆果子有xi个,每个果子的重量为1,小明每次把i,j两堆果子移成一堆,需要花费的体力为xi+xj。最后移成一堆,求最小花费体力值。
其中1<=n<=10000,1<=m<=10000。均为正整数。Input

    每组数据第一行输入一个正整数n,表示有n堆果子。

    接下来一行有n个正整数,表示每堆果子的重量。

    输入以EOF结尾。

Output    每组数据单独一行,输出所花费的最小体力值。


Sample Input

3

1 2 9

5

1 3 9 18 30

 

Sample Output

15

109

首先可以贪心地每次将最小和第二小的果堆合起来,可是合成后的堆不一定比原来第三小的堆小,如33456合成后就变成6456,显然6+4>4+5,因此我们需要动态排序,由此想到了优先队列.

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 const int amn=1e5+5;
 5 int a[amn];
 6 int n;
 7 void sd(int i)
 8 {
 9     int t;
10     while(2*i<=n)
11     {
12         if(a[i]>a[2*i])t=2*i;///先判断左孩子
13         else t=i;
14         if(2*i+1<=n&&a[t]>a[2*i+1])t=2*i+1;///如果右孩子存在,则判断右孩子
15         if(t!=i)
16         {
17             swap(a[i],a[t]);
18             i=t;///注意要更新编号,下一次循环才会继续调整;
19         }
20         else break;
21     }
22 }
23 void up(int i)
24 {
25     int t;
26     while(i<=1)
27     {
28         if(i/2<=1&&a[i]<a[i/2])t=i/2;
29         else t=i;
30         if(t!=i)
31         {
32             swap(a[i],a[t]);
33             i=t;
34         }
35         else break;
36     }
37 }
38 void create()
39 {
40     for(int i=n/2;i>=0;i--)
41     sd(i);
42 }
43 int del()
44 {
45     int t=a[1];
46     a[1]=a[n];
47     n--;
48     sd(1);
49     return t;
50 }
51 void push(int i)
52 {
53     a[++n]=i;
54     sd(n);
55 }
56 int main()
57 {
58     while(cin>>n)
59     {
60         for(int i=1;i<=n;i++)
61             cin>>a[i];
62         create();
63         int ans=0;
64         while(1)
65         {
66             int tmp=del();
67             tmp+=del();
68             ans+=tmp;
69             if(!n)break;///注意在这里空了就要跳出,否则会合出原来就不存在的堆
70             push(tmp);
71         }
72         cout<<ans<<endl;
73     }
74 }

 

全部评论

相关推荐

11-07 13:31
怀化学院 Java
勇敢牛牛不怕难:又疯一个
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务