堆排序 P1090 合并果子

 

P1090 合并果子

        本题要用到堆

       一个小根堆

       每次取出两堆,合并成一堆,为了让多多花费体力最少,我们要尽量少的重复大堆的合并,因此每次合并完以后,要把新的一坨放到堆里排一排,维护一个堆

 

有必要强调一下这个合并的操作:

(1)取出最小的一个(或一坨)果子 x

(2)再取出最小的一个(或一坨)果子 y

(3)合并为一坨 x+y 

(4)体力值自然要加上 x+y 了

(5)把 x+y 放到堆里维护一下这个堆,保证下次从堆中取出小的一个或一坨

 

 

【代码】:

#include<bits/stdc++.h>

using namespace std;

int n,guo,heap_size,ans=0,ans1=0,x,y;
int heap[10001];

void put(int d)     //小根堆入堆
{
    int now,next;
    heap[++heap_size]=d;
    now=heap_size;
    while(now>1)
    {
        next=now>>1;
        if(heap[now]>=heap[next]) break;
        else swap(heap[now],heap[next]);
        now=next;
    }
}

int get() //小根堆出堆 { int now,next,res; res=heap[1]; heap[1]=heap[heap_size--]; now=1; while(now*2<=heap_size) { next=now*2; if(next<heap_size&&heap[next+1]<heap[next]) next++; if(heap[now]>heap[next]) swap(heap[now],heap[next]); now=next; } return res; }

int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&guo); put(guo); } for(int i=1;i<n ;i++) //每次把两堆果子合为一堆,一共需要合并n-1次 { x=get(); //取出一堆小果子 y=get(); //再取出一堆小果子 ans+=x+y; //体力等于搬运这两个之和 put(x+y); //把这两个放进堆 } cout<<ans; return 0; }

 

posted @ 2019-04-26 21:01  晔子  阅读(366)  评论(0编辑  收藏  举报