题目来源:[NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G - 洛谷
参考书目:《深入浅出程序设计竞赛(基础篇)》
解题思路:这道题的关键在于每次选择合并时都要选择最小的两堆果子来合并,从而保证每次合并的代价最小,累计的总代价也最小。可以使用两个数组,一个存储输入的果子数目(a1),另一个用于存储中间合并过程中生成的新堆(a2)。
图1 节选自《 深入浅出程序设计竞赛(基础篇)》
解题步骤
-
输入果子的种类数n,并为a1数组赋予相应的果子数目。
-
将a1数组进行升序排序。
-
初始化两个指针,分别指向a1和a2的起始位置,用于在后续操作中选择最小的元素。
-
进行n-1次操作,每次从a1和a2指向的元素中选取两个最小的进行合并,更新指针位置,并将合并后的新重量加入到a2数组,同时更新总体力消耗sum。
-
在所有果子合并完成后,输出总体力消耗sum作为答案。
#include<iostream>
#include<algorithm>
#include<cstring>using namespace std;int n, n2, a1[10010], a2[10010], sum = 0;int main()
{cin >> n;memset(a1, 127, sizeof(a1));//将数组初始化为一个接近int最大值的数,效率较高memset(a2, 127, sizeof(a2));for (int i = 0; i < n; i++){cin >> a1[i];}sort(a1, a1 + n);int i = 0, j = 0, k, w;for (k = 1; k < n; k++){w = a1[i] < a2[j] ? a1[i++] : a2[j++];//取最小值w +=a1[i] < a2[j] ? a1[i++] : a2[j++]; //取第二次最小值a2[n2++] = w;//加入第二个队列sum += w;//计算价值}cout << sum;return 0;}