算法题每日一练---第30天:部落谈判

522 阅读2分钟

「这是我参与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;
}

五、输出结果

1.png