您的位置:首页 > 其它

合并果子

2017-07-28 13:38 134 查看

经典二叉堆——合并果子

萌新第一次写博客233,为了记录一下这道经典的题的二叉堆做法。(以后再忘记就尴尬了233)。

原题:合并果子

1.基本二叉堆的建立:

–建立一个小根堆

void binary_heap(int x)
{
while(x/2>=1)
{
int j=x/2;
if(a[j]>a[x])
{
swap(a[j],a[x]);
x=j;
}
*else
{
break;
}*
}
}


2.进行删除与调整操作(a[1])

–每次将新的元素放置在A【1】时,将它调整至合适的位置

void rise(int y)
{
while(y*2<=tot)//由于合并果子是每次将两个果子合并为一个,所以每次都会少一个“儿子”,这时候就需要将总数进行调整
{                       (开始时int tot=n;每次进行删除调整时tot--)
int k=y*2;
if(y*2+1<=tot&&a[y*2+1]<a[y*2}) k++;
if(a[k]<a[y]) swap(a[k],a[y]);
*else break;*
}
}


3.合并果子的调整操作

由于要消耗体力最小,所以每次合并之后将新的果子找到自己的位置,使其一直保持为小根堆的形态。合并时,先使ex+=a1,然后舍弃掉a1.之后紧接着进行一次小根堆的调整。这时再使ex+=a[1],a[1]=ex,然后rise(1).重复操作n次,结果就是最小的值。

4.代码如下

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int ex;
int a[11000];
int ans=0;
int tot;
int vis[11000];
int swapp;
void binary_heap(int x)
{
while(x/2>=1)
{
int j=x/2;
if(a[j]>a[x])
{
swapp=a[j];
a[j]=a[x];
a[x]=swapp;
x=j;
}
else
{
break;
}
}

}
void rise(int y)
{
while(y*2<=tot)
{
int k=y*2;
if(y*2+1<=tot&&a[y*2+1]<a[y*2])
{
k++;
}
if(a[y]>a[k])
{
swapp=a[y];
a[y]=a[k];
a[k]=swapp;
y=k;
}
else break;
}
}
int main()
{
cin>>n;
tot=n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
binary_heap(i);
}
for(int i=1;i<n;i++)
{
ex=0;
ans+=a[1];
ex+=a[1];
a[1]=a[tot];
tot--;
rise(1);
ans+=a[1];
ex+=a[1];
a[1]=ex;
rise(1);
}
cout<<ans;
return 0;
}


//////
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  博客