有n堆石子,每次取出两堆合成一堆,每堆石子的个数即为合并石子所需要耗费的体力,求出合并所有石子堆所需要耗费的最小体力

有n堆石子,每次取出两堆合成一堆,每堆石子的个数即为合并石子所需要耗费的体力,求出合并所有石子堆所需要耗费的最小体力

典型的贪心题,即每次取出数量最少的两堆石子合并.

举个例子来说,假如有5堆石子,石子个数分别为
1 2 3 4 5

为了使得耗费的体力最小,我们需要每次合并石子数最小的和次小的两堆石子

第一次
1 + 2 ,耗费3点体力

石子堆变为
3 3 4 5

第二次
3 + 3 ,耗费6 点体力

石子堆变为
6 4 5

第三次
4 + 5 ,耗费9点体力

石子堆变为
6 9

最后一次
6 + 9 ,耗费15点体力

此时石子已经完成合并,变为一堆

所以耗费的最小体力为

3 + 6 + 9 + 15 = 33点体力

将其转换为编程思路

可以利用C++中的 multiset 容器(对插入的数据进行自动排序,这样我们可以每次取前两个数据,也就是最少的两堆石子),考虑到合并石子之后石子的个数可能会和原有石子堆的个数相同,而set容器会自动去重,所以用 multiset

完整代码如下:

#include <iostream>
#include <set>

using namespace std;

int main()
{
	int n;
	cin >> n; //石子的堆数

	multiset<int> data; //合并石子后石子个数可能会和原有的某堆石子个数相同,所有选择 multiset(set会自动去重)
	multiset<int>::iterator is;

	int tmp;
	int sum = 0;

	for (int i = 0; i < n; ++i)
	{
		cin >> tmp;	//输入每堆石子的个数
		data.insert(tmp);
	}

	while (data.size() > 1)
	{
		tmp = 0;
		is = data.begin();
		tmp += *is;
		data.erase(is);
		

		is = data.begin();
		tmp += *is;
		data.erase(is);

		data.insert(tmp);

		sum += tmp;
	}

	cout << sum << endl;

	system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值