有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;
}