2024年寒假算法班集训day04-知识总结及题解(贪心)

本文介绍了贪心算法的基本思想和适用性,并通过多个实例(如找零钱问题、胡萝卜问题、节省时间问题、士兵突击问题等)详细解析了贪心算法的解题步骤。贪心算法在解决问题时,每次都选取当前最优解,但并不保证一定能得到全局最优解,适用于一些特定的优化问题。通过合理设计贪心策略,可以有效解决一系列问题。
摘要由CSDN通过智能技术生成

概念

贪心算法是一种在每一步选择中都采取当前状态下最优的选择,希望通过一系列局部最优的选择,达到全局最优解的算法思想。简而言之,就是“每次都选最好的”。但它不一定能得到最终的最优解,因此适用性有限。例如,在找零钱问题中,我们通常会先用面值大的钱币,以减少钱币的数量。在实际应用中,我们需要区分问题是否适合用贪心算法解决,这通常需要通过数学证明来确认。此外,贪心算法的设计思路简洁,实现容易,是入门算法设计的良好选择。通过分析问题特点,合理设计贪心策略,我们可以有效地解决一系列优化问题。

1、贪心的小童-2909
在这里插入图片描述
题解:

程序目的是计算四堆胡萝卜中各自最重的一根的总重量。对于每一堆胡萝卜,首先记录下所有胡萝卜的重量,然后在该堆中找出最重的胡萝卜,最后将四堆中最重的胡萝卜重量求和。

步骤如下:

  1. 使用一个数组 a 来存储每堆胡萝卜的重量。
  2. 用循环读入每堆胡萝卜的数量 n 和对应的每个胡萝卜的重量,并存入数组 a
  3. 在每次循环中,定义一个变量 t 用来暂存每堆胡萝卜中最重的重量。
  4. 通过内层循环,比较当前堆中的每个胡萝卜重量与 t 的大小,若当前胡萝卜重量更大,则更新 t
  5. 每次外层循环结束后,将 t(当前堆中最重的胡萝卜重量)累加到总和 sum 上。
  6. 四次循环结束后,sum 存储的就是四根最重胡萝卜的总重量。
  7. 输出 sum

代码中,数组 a 的大小被设置为1010,是为了确保能够存储最多1000个胡萝卜的重量。最后输出的 sum 就是所求的四根胡萝卜总重量的最大值。

#include <bits/stdc++.h>
using namespace std;
int a[1010],n,sum=0;
int main(){
   
	for(int i=1;i<=4;i++){
   
		cin>>n;
		for(int j=1;j<=n;j++)
			cin>>a[j];//输入n个胡萝卜的重量。
		int t=0;//定义一个变量,存储每堆胡萝卜重量的最大值。
		for(int j=1;j<=n;j++)
			//胡萝卜的重量大于t,就更新t的值。求出每一堆的最优结果。
			if(a[j]>t) t=a[j];
		sum+=t;//累加每堆最重胡萝卜的重量,得到最终的最优结果。
	}
	cout<<sum<<endl;
	return 0;    
} 

2、节省时间-2908
在这里插入图片描述
题解:

程序的目的是找出一种排队顺序,使得所有学生的答疑完成时间的平均值最小。根据调度理论中的SJF(Shortest Job First,最短作业优先)策略,我们知道最优的答疑顺序是按照答疑时间从短到长排序的。

以下是解题步骤:

  1. 读入学生数量 n 和每个学生的答疑时长存入数组 a
  2. 对数组 a 进行升序排序,使得答疑时间短的学生排在前面。
  3. 初始化一个变量 s 来记录所有学生的答疑完成时间之和。
  4. 通过一个循环,计算每个学生的答疑完成时间,并累加到 s 上。对于第 i 个学生,其答疑完成时间等于其自身的答疑时间 a[i] 加上其前面所有学生答疑时间的总和。
  5. 在循环中,用 (n-i)*a[i] 计算当前学生答疑时,后面的学生需要等待的总时间,并将其加到 s
  6. 循环结束后,s 包含了所有学生的答疑完成时间之和。
  7. 使用 s 除以学生总数 n 并保留两位小数输出,即为所求的最小平均答疑完成时间。

代码中使用了 fixedsetprecision(2) 来设置输出的浮点数精度为小数点后两位。最终输出的结果是所有学生的答疑完成时间的平均值。

#include <bits/stdc++.h>
using namespace std;
int a[1010],n;
int main(){
   
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	sort(a+1,a+n+1);//按照答疑时间升序排序
	int s=0;
	for(int i=1;i<=n;i++){
   
		//第1个人的答疑时间是后面n-1个人的等待时间,第i个人的答疑时间是后面n-i个人的等待时间
		s+=(n-i)*a[i]+a[i]; //最后加上自己的答疑时间a[i] (n-i)*a[i]+a[i]
	}
	cout<<fixed<<setprecision(2)<<s*1.0/n;
	return 0;
} 

3、士兵突击-2910
在这里插入图片描述
题解:

这个问题可以通过贪心算法来解决,即每次选择体重最轻的士兵上船,直到船的载重量无法再装载更多的士兵为止。这样可以确保装载的士兵数量最多。

步骤如下:

  1. 读入士兵的数量 n 和船的载重量 c
  2. 读入每个士兵的体重,并将体重存入数组 w
  3. 对数组 w 进行排序,使士兵按体重从轻到重排列。
  4. 初始化变量 tmp 为0,用于记录当前船上士兵的总体重;初始化 ans 为0,用于记录上船的士兵数量。
  5. 从最轻的士兵开始,依次尝试将每名士兵上船,即累加他们的体重到 tmp
  6. 如果 tmp 加上当前士兵的体重仍然小于等于船的载重量 c,则将这名士兵算作已上船,ans 加1。
  7. 如果加上当前士兵体重后 tmp 超过了 c,则停止尝试,因为不能再装载更多的士兵。
  8. 最后输出 ans,即为最多可以装载的士兵数量。
#include <bits/stdc++.h>
using namespace std;
int main(){
   
	//定义变量和数组
	int n,c,w[2002]={
   };
	//输入士兵个数n和船载重量
	cin>>n>>c;
	//输入n个士兵兔体重
	for(int i=0;i<n;i++
  • 11
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值