「这是我参与2022首次更文挑战的第31天,活动详情查看:2022首次更文挑战」
一、问题描述
在很久很久以前,有 n 个部落居住在平原上,依次编号为 1 到 n。第 i个部落的人数为 ti。
有一年发生了灾荒。年轻的政治家小蓝想要说服所有部落一同应对灾荒,他能通过谈判来说服部落进行联合。
每次谈判,小蓝只能邀请两个部落参加,花费的金币数量为两个部落的人数之和,谈判的效果是两个部落联合成一个部落(人数为原来两个部落的人数之和)。
二、题目要求
输入描述
输入的第一行包含一个整数 n,表示部落的数量。
第二行包含 n 个正整数,依次表示每个部落的人数。
其中,1≤n≤1000,1≤ti≤10^4。
输出描述
输出一个整数,表示最小花费。
测试数据
输入4个数字分别为9 1 3 5,输出结果为31
三、问题分析
这是一道考察贪心最优解的问题,题目要求将n个部落聚合到一起,使之花费最少,那我们每一次谈判都邀请人数最少的两个部落不就行了。
以测试数据为例,先进行一次排序:1 3 5 9
1 3合在一起变成4,4重新加入后排序4 5 9
4 5合在一起变成9,重新加入后排序9 9
最后,所有结果相加:4+9+9+9=31
排序可以使用C++中的排序函数,不需要自己编写,那两个数字相加重新加入的数字怎么办?
第一步1 3合并成4,我们可以让4赋值给3,1变成0,那么数组的大小没变,排序也不受影响。
1 3合在一起变成4,4重新加入后排序0 4 5 9
4 5合在一起变成9,重新加入后排序0 0 9 9
最后,所有结果相加:4+9+9+9=31
拓展
C++头文件algorithm中的sort函数:
以数组为例a[4]={3,4,1,2} , sort(a,a+4) 输 出 1 2 3 4
四、编码实现
#include<iostream>
#include<algorithm>
using namespace std;
long long int a[10008],sum=0;//初始化定义,应该不会超范围
int main()
{
int i,n;
cin>>n;//输入部落
for(i=0;i<n;i++)
cin>>a[i];//输入部落人数
sort(a,a+n);//初始化排序
for(i=0;i<n-1;i++)
{
int min=a[i]+a[i+1];//定义min存储数组内最小的两个元素
a[i]=0;//第一个元素为0
a[i+1]=min;//第二个元素为min
sum+=min;//sum++
sort(a,a+n);//排序
}
cout<<sum;//输出结果
return 0;
}