贪心算法

是一种在每一步选择中都采取在当前看来是最优的选择,希望通过一系列局部最优选择,从而得到一个全局最优解的算法策略。

贪心算法的基本思想是:在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,所做出的仅是在某种意义上的局部最优解。

贪心算法的应用领域很广泛,例如:

  1. 找零钱问题:在给定不同面额的货币时,以最少的货币数量找零。
  2. 活动安排问题:在多个活动具有开始时间和结束时间的情况下,选择最多的兼容活动。
  3. 背包问题:在有限容量的背包中,选择价值最大的物品放入背包。

在 CSP(计算机软件能力认证)考试中,贪心算法可能会作为以下考点出现:

  1. 对贪心算法基本概念的理解,例如判断给定的问题是否适合用贪心算法解决。
  2. 贪心策略的设计和分析,要求考生能够根据具体问题设计出合理的贪心策略。
  3. 贪心算法的代码实现,包括对问题的建模和算法的具体编码。

本次课对应的做题网站 https://qqwhale.com/group/1408/training/30202/problems
对于本次课的代码全解↓

4458 分配礼物

#include<bits/stdc++.h>
using namespace std;
int main(){
	int a[105]={};
	int n,y;
	cin>>n>>y;
	for(int i=1;i<=n;i++)	cin>>a[i];
	sort(a+1,a+n+1);  //按礼物价值升序
	int i=1,j=n; //i表示价值最小礼物 j表示价值最大礼物
	int two=0; //表示两个礼物一组的组数
	while(i<j){
		if(a[i]+a[j]>y) //价值和超过y,价值高的自己1组 
			j--;
		else{ //没有超过y,两个礼物放1组
			i++;
			j--;
			two++;
		}
	}
	cout<<two;
	return 0;
}

4454 上船问题

#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[201];
int main()
{
	//n为人数,m为一条船的最大承重
	cin>>n>>m;
	//输入体重
	for(int i=1;i<=n;i++) cin>>a[i];
	//体重从小到大排序
	sort(a+1,a+n+1);
	//i表示最轻体重下标位置,j表示最重体重下标位置
	int i=1,j=n;
	//记录所用船数
	int cnt=0;
	//遍历所有船员
	while(i<=j)
	{
		//判断最轻和最重船员是否超过载重
		if(a[i]+a[j]>m) {
			j--;//超过载重就选择更轻的船员
			cnt++;//记录船的数量
		}
		else
		{
			//切换下一组最轻、最终
			i++;
			j--;
			cnt++;//记录船的数量
		}
	}
	//输出最终解
	cout<<cnt<<endl;	
	return 0;
}

4453 购物竞赛

#include<bits/stdc++.h>
using namespace std;
//创建表示商品属性的结构体
struct cmdt{
	int price, num, ave;
}box[110];
//排序规则-单价从大到小排序
bool cmp(cmdt x, cmdt y) {
	return x.ave>y.ave;
}
int main() {
	int n=0, l=0, sum=0;
	cin>>n>>l;
	for (int i=0; i<n; i++) {
		//输入商品价值及数量
		cin>>box[i].price>>box[i].num;
		//计算商品单价
		box[i].ave=box[i].price/box[i].num;
	}
	//按照单价从大到小排序
	sort(box, box+n, cmp);
	//遍历商品种类
	for (int i=0; i<n; i++) {
		//当前商品价值全部累加
		if (box[i].num<l) {
			sum+=box[i].price;
			l-=box[i].num;
		//当前商品价值部分累加
		} else {
			sum+=box[i].ave*l;
			break;
		}
	}
	cout<<sum;
	return 0;
}

2911 突飞猛进

#include<bits/stdc++.h>
using namespace std;
struct node{
	//s会议开始时间,e会议结束时间
	int s,e;
}T[1010],tmp;
bool cmp(node x,node y){
	//按照会议结束时间升序排列
	return x.e<y.e;
}
int main(){
	int n=0;
	cin>>n;
	for(int i=0;i<n;i++)
	    cin>>T[i].s>>T[i].e;
	sort(T,T+n,cmp);//结构体数组排序
	int sum=1;//统计会议数,第1个会议先统计
	tmp=T[0];//临时存储已选会议
	for(int i=1;i<n;i++){//从第二个会议开始遍历
		if(T[i].s>=tmp.e) {//当前会议的开始时间 >=上个会议的结束时间
			sum++;//符合条件,会议不冲突,累加会议数
			tmp=T[i];//更新已选会议
		}
	} 
    cout<<sum;//输出结果
	return 0;
}

2910 士兵突击

#include <bits/stdc++.h>
using namespace std;
int main() {
	//定义变量和数组
	int n,c,w[2001]= {};
	//输入士兵个数n和船载重量
	cin>>n>>c;
	//输入n个士兵兔体重
	for(int i=0; i<n; i++)
		cin>>w[i];
	//按照体重升序排序
	sort(w,w+n);
	//tmp计算上船的总体重ans数量
	int tmp=0,ans=0;
	for(int i=0; i<n; i++) {
		//从体重最小士兵开始依次上船
		tmp+=w[i];
		//上船士兵兔总重量小于载重量
		if(tmp<=c)
			ans++;  //统计士兵数量
		else
			break;  //否则终止循环
	}
	cout<<ans;
	return 0;
}

2909 贪心的小童

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

2908 节省时间

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


2381 可可岛的宝藏

#include<bits/stdc++.h>
using namespace std;
struct node{
	//结构体存储重量和价值
	int wei,v;
	//用来存储单位价值
	double p;
}b[210];
int k,w,s;
bool my_cmp(node x,node y){return x.p>y.p;}//按照单位价值降序排序
int main(){
    cin>>k;
	//输入k组数据
    while(k--){
    	cin>>w>>s;
    	double sum=0;//在while循环里面初始化
    	for(int i=1;i<=s;i++){
    		cin>>b[i].wei>>b[i].v;
    		b[i].p=b[i].v*1.0/b[i].wei;//计算单位价值
	    }
		//排序
	    sort(b+1,b+s+1,my_cmp);
	    for(int i=1;i<=s;i++){
		    if(w-b[i].wei>=0){//能装入
			    w-=b[i].wei;//装入,减去物品重量
			    sum+=b[i].v;//计算装入物品的价值
		    }
		    else{//不能装入
		        sum+=w*b[i].p;//装一部分
			    break;//终止循环
		    }
	    }
		cout<<fixed<<showpoint<<setprecision(2)<<sum<<endl;//输出一定要加换行
     }
     return 0;
} 

1743 童童看节目

#include<bits/stdc++.h>
using namespace std;
struct Node{
	int s;
	int e;
};
Node a[105];
bool cmp(Node x,Node y){
	if(x.e!=y.e)	return x.e<y.e;
	else	return x.s<y.s;
}
int main(){
	int n;
	cin>>n;
	while(n!=0){ //n不等于0就继续
		for(int i=1;i<=n;i++)
			cin>>a[i].s>>a[i].e;
		sort(a+1,a+n+1,cmp); //结束时间早的在前
		int s=1;//统计节目数量,默认第1可以看
		Node t=a[1];//t记录已统计的最后1个节目
		for(int i=2;i<=n;i++){
			//当前节目开始时间不小于t的结束时间
			if(a[i].s>=t.e){
				s++;
				t=a[i];
			}
		}
		cout<<s<<endl;
		cin>>n; //输入下1组n,如果n=0则退出while
	}
	return 0;
}


1547 童程同学讲礼貌

#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++){
		//计算等待时间
        s+=(n-i+1)*a[i];
    }
    cout<<fixed<<showpoint<<setprecision(2)<<s*1.0/n;
    return 0;
}

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐