目录
必看信息
▶本篇文章由爱编程的小芒果原创,首发于CSDN,未经许可,严禁转载。
▶本篇文章被收录于秒懂百科,C++如此简单专栏,欢迎订阅。
☆专栏亮点☆
1.每篇文章质量高,质量分保证在80分以上。
2.文章的内容清晰有条理,图文并茂,附有源代码。
3.每个知识点讲解详细,会有很多补充扩展。
4.若哪个知识点没有懂,可以私信我,我会尽可能地帮助你。
Everyday English
One minute on the stage needs ten years practice off stage.
台上一分钟,台下十年功
引子
什么是贪心?
其实就是遵循某种规则,不断贪心地选取当前最优策略地算法设计方法。
简单来说,就是用最优策略去解问题。
那做题的框架呢?
没有框架!就是找到贪心的思路,照着编就行了。
我个人认为,贪心其实跟数学逻辑息息相关。就是用数学逻辑去找到或思考贪心思路,再用程序写出来。因此贪心的两大主要步骤就是确定贪心思路和编程!
话不多说,我们来看几道例题。
1、纸币问题
题目概要
现有纸币1元,5元,10元,20元,50元,100元若干枚,要求分别输入这些面值硬币的个数,以及一个总钱数a元。问:至少用多少个硬币才能凑出a元?
解题思路
根据直觉和生活中的常识,我们可以得到以下解答:
先尽可能地使用100元的硬币。
剩下的再尽可能地使用50元的硬币。
剩下的再尽可能地使用20元的硬币。
剩下的再尽可能地使用10元的硬币。
剩下的再尽可能地使用5元的硬币。
最后使用1元的硬币。
示范代码
#include<bits/stdc++.h>
using namespace std;
int v[6]={1,5,10,20,50,100};
int main(){
int c[6],a,ans=0;
for(int i=0;i<6;i++) cin>>c[i];
cin>>a;
for(int i=5;i>=0;i--){ //倒序,优先使用大面值的硬币
int x=min(c[i],a/v[i]); //使用x张该面值的硬币,min来检查这个面值的张数够不够
ans+=x;//加上张数
a-=x*v[i];//总钱数减去当前面值最大用去的
}
cout<<ans<<endl;
return 0;//好习惯
}
2、洛谷(P1658 购物 C++)
题目概要
题目描述:
你就要去购物了,现在你手上有 N种不同面值的硬币,每种硬币有无限多个。为了方便购物,你希望带尽量少的硬币,但要能组合出 1到 X 之间的任意值。
输入格式:
第一行两个数 X, N,以下 N 个数,表示每种硬币的面值。
输出格式:
最少需要携带的硬币个数,如果无解输出 -1。
输入输出样例:
输入:20 4 输出:5
1 2 5 10
解题思路
这道题是一道经典的贪心问题,你得先弄清楚贪心策略
首先,我们必须得有一枚1元面值的硬币,如果没有的话,就是无解,因为你凑不出1元。
下面我们就得列举找规律了(先不按每种面值无限张算,就按每种只有一张算):
有了面值1元,就一定要有面值2元的,不然你凑不出2元:目前面值:1元、2元
接着想,需不需要3元呢?其实是不需要的,因为1元和2元可以凑出3元;目前面值:1元、2元
那四元呢?那就必须要了,无论用前面所有的面值也凑不到4元。目前面值:1元、2元、4元
五元?可以用1元和4元凑成,不用! 目前面值:1元、2元、4元
六元?可以用2元和4元凑成,不用! 目前面值:1元、2元、4元
七元?可以用1元、2元和4元凑成,不用! 目前面值:1元、2元、4元
八元?前面三个面值怎么也凑不成,必须要用! 目前面值:1元、2元、4元、8元
以此类推会得到这样的数列:1元、2元、4元、8元、16元、32元、64元……
由次我们发现了一个规律:每新来一枚硬币,它的值只可能小于等于前面所有面值和+1
知道了贪心策略,代码就迎刃而解了!
示范代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int sum,cnt,n,x,a[1005];//sum表示目前硬币面值总和,cnt表示硬币数
cin>>x>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);//从小到大排序,保证小的在前
//如果没有一元的硬币,就凑不出1元,所以无解
if(a[1]!=1)
{
cout<<"-1"<<endl;
return 0;
}
sum=1; cnt=1;//初始必定要一枚一元,目前sum=1,cnt=1
while(sum<x)//一直循环,知道能凑出最大的那个面值为止
{
int p=0;//指针
for(int i=1;i<=n;i++) if(a[i]<=sum+1) p=i;//贪心思路
sum+=a[p];
cnt++;
}
cout<<cnt<<endl;
return 0;
}
结尾
你学会了吗?还不赶紧去试试?
对了,我是爱编程的小芒果,喜欢我的文章记得点个免费的赞哦!下次我们讲dfs深搜算法!Bye!