合併果子(堆寫法)

題目大意:

一個小朋友從樹上打下了幾堆果子。要將所有果子合併成一堆。給出沒堆果子的重量求最小力氣

本題的思路是要將重量最小的先合併,也就是傳說中的哈夫曼樹!但本題的數據比較大。今天我們來看堆得寫法:

# include<stdio.h>
# include<stdlib.h>
long long a[1000010];
int main(){
    long long sum=0,ans=0,n,i,h,r,j;//本題要用long long不然會答案錯誤
    scanf("%I64d",&n);
    for(i=1;i<=n;i++){
        scanf("%I64d",&a[i]);//將重量存入堆
         r=i;//上浮
        while(r>1&&a[r]<a[r/2]){ 
            h=a[r];
            a[r]=a[r/2];
            a[r/2]=h;
            r/=2;
        }
    }
    int len=n;
    for(i=1;i<n;i++){
        sum=a[1];//將當前最小的放到本次合併中
        a[1]=a[len];
        len--;
        r=1;//下沉
        while((r*2<=len&&a[r]>a[r*2])||(r*2+1<=len&&a[r]>a[r*2+1])){
            j=r*2;
            if(j+1<=len&&a[j]>a[j+1])j++;
            h=a[r];
            a[r]=a[j];
            a[j]=h;
            r=j;
        }
        sum+=a[1];//將第二小的加入本次合併中
        a[1]=a[len];
        len--;
        r=1;//下沉
        while((r*2<=len&&a[r]>a[r*2])||(r*2+1<=len&&a[r]>a[r*2+1])){
            j=r*2;
            if(j+1<=len&&a[j]>a[j+1])j++;
            h=a[r];
            a[r]=a[j];
            a[j]=h;
            r=j;
        }
        ans+=sum;//合併
        a[++len]=sum;
        r=len;//上浮
        while(r>1&&a[r]<a[r/2]){
            h=a[r];
            a[r]=a[r/2];
            a[r/2]=h;
            r/=2;
        }
    }
    printf("%I64d\n",ans);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章