一、贪心算法是什么?
主要知识点
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。 也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。 贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。基本思路:⒈ 建立数学模型来描述问题。 ⒉ 把求解的问题分成若干个子问题。 ⒊ 对每一子问题求解,得到子问题的局部最优解。⒋设计框架,综合局部最优解,得到整体最优解。
适用场景
1、单源最短路经问题
2、最小生成树问题
3、可任意分割的背包问题。如果不可以任意分割,就需要用动态规划求解。
4、某些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。
5、活动安排
…
不适用场景
1、选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关
2、局部最优解堆叠的结果不是整体最优解时不能使用
例如从4元、6元、8元中拿取不大于10元的钞票,它的局部最优解是每次拿取最大数额的钱,整体最优解是拿到总金额最大的钱,也就是说使用贪心算法时只能拿到8元,而正确答案应该是10元。
二、算法示例
Yogurt factory
Description
The cows have purchased a yogurt factory that makes world-famous Yucky Yogurt. Over the next N (1 <= N <= 10,000) weeks, the price of milk and labor will fluctuate weekly such that it will cost the company C_i (1 <= C_i <= 5,000) cents to produce one unit of yogurt in week i. Yucky’s factory, being well-designed, can produce arbitrarily many units of yogurt each week.
Yucky Yogurt owns a warehouse that can store unused yogurt at a constant fee of S (1 <= S <= 100) cents per unit of yogurt per week. Fortuitously, yogurt does not spoil. Yucky Yogurt’s warehouse is enormous, so it can hold arbitrarily many units of yogurt.
Yucky wants to find a way to make weekly deliveries of Y_i (0 <= Y_i <= 10,000) units of yogurt to its clientele (Y_i is the delivery quantity in week i). Help Yucky minimize its costs over the entire N-week period. Yogurt produced in week i, as well as any yogurt already in storage, can be used to meet Yucky’s demand for that week.
Input
-
Line 1: Two space-separated integers, N and S.
-
Lines 2…N+1: Line i+1 contains two space-separated integers: C_i and Y_i.
Output
- Line 1: Line 1 contains a single integer: the minimum total cost to satisfy the yogurt schedule. Note that the total might be too large for a 32-bit integer.
Sample Input
4 5
88 200
89 400
97 300
91 500
Sample Output
126900
题解:
从题意可看出只要我们求得每个星期的最优解(局部最优解)后再相加便可得到全体最优解(总体最优解)。
从题目可得出第i星期对于第x星期(x<=i)的机器的造价m为m=(i-x)*S+Ci,同时我们发现上个星期的局部最优解可以作为上个星期以前对于这个星期的局部最优解,从而我们只需比较m_(i-1)+S与Ci,取最小值作为这个星期的最优解。
代码如下
#include <iostream>
using namespace std;
int main() {
int N, S;
cin >> N >> S;
long long sum=0,last=0;
int Ci=0, Yi=0,n = N - 1;
while (N--){
cin >> Ci >> Yi;
if (N == n){
last = Ci;
sum += last * Yi;
continue;
}
if (last + S <= Ci){
last = last + S;
sum += last * Yi;
}
else{
last = Ci;
sum += last * Yi;
}
}
cout << sum;
return 0;
}
bug
一开始提交这个题目时一直有一个WA,而学校给的oj又不给测试数据,我一度在代码里疯狂地寻找bug却一无所获。最后在快要抓狂的时候看了大佬的题解,才发现是因为int溢出了…所以说根据数据范围选择合适的数据类型真的很重要啊…
总结
以上就是这章要讲的内容,这里仅仅简单介绍了贪心算法,而进阶的理解还是去找找大佬的博客吧QAQ