果子合并(数据结构小实验)用堆来做

题目四:果子合并(***)

[问题描述]

n堆果子, 每堆果子数量任意,试设计一种最佳方案,将这n堆果子合并为一堆,使得合并工作量最小。
注:规定合并两堆果子的工作量是这两堆果子的数量之和。

[标准输入]

M,N 。 M表示M组测试数据,N表示每组测试数据数量有N个,每堆果子数量不超过10000。随后的M行是测试数据。

[标准输出]

M行数据表示对应果子的合并工作量

[输入样例]:

2
4
7 5 2 4
5
5 6 2 9 7

【输出样例】:

35
65

#include<stdio.h>
#include<string.h>
const int MAXN=100000;
int heap[MAXN],size=0;
void push(int x){
   int i=size++;//把新加入的数据放进最后一个叶子节点
   while(i>0){
   	int p=(i-1)/2;
   	if(heap[p]<x) break;
   	heap[i]=heap[p];
   	i=p;
   }//谁小谁上去
   heap[i]=x;
}
int pop(){
   int ret=heap[0];//把根提出来
   int x=heap[--size];//最后一个叶子节点提到根的位置
   int i=0;
   while(i*2+1<size){//谁小谁上去
   	int a=i*2+1,b=i*2+2;
   	if(b<size&&heap[b]<heap[a]) a=b;
   	if(heap[a]>=x) break;
   	heap[i]=heap[a];//数据提上去
   	i=a;//下标改变
   }
   heap[i]=x;
   return ret;
}
int main()
{
   int t;
   scanf("%d",&t);
   while(t--)
   {
   	memset(heap,0,sizeof(heap));
   	int n;
   	scanf("%d",&n);
   	for(int i=0;i<n;i++){
   		int temp;
   		scanf("%d",&temp);
   		push(temp);
   	}
   	int ans=0;
   	while(size>1){//每次提出最小的两个合并后把新生成的节点放在叶子节点的位置
   		int a=pop();
   		int b=pop();
   		ans=ans+a+b;//计算代价
   		push(a+b);
   	}
   	printf("%d\n",ans);
   }
   return 0;
}

总结

经典的贪心思想,与哈夫曼树一样,考虑到最先调用过的以后还会再,越靠近根的位置累计调用次数越少,那么可以让调用代价小的先合并,所以手写一个堆即可,之后把每两个最小的堆顶合并成新结点加入到堆中。用ans累加这种新结点即可得到最终答案。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值