c++贪心算法简单介绍

6 篇文章 0 订阅
1 篇文章 0 订阅

一、贪心算法是什么?

主要知识点

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。 也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。 贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。基本思路:⒈ 建立数学模型来描述问题。 ⒉ 把求解的问题分成若干个子问题。 ⒊ 对每一子问题求解,得到子问题的局部最优解。⒋设计框架,综合局部最优解,得到整体最优解。

适用场景

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

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++贪心法背包问题可以通过以下步骤解决: 1. 首先,定义一个结构体或类来表示物品,包括物品的重量和价值。 ```cpp struct Item { int weight; int value; }; ``` 2. 创建一个函数来比较两个物品的价值密度(价值除以重量),并按照价值密度从大到小排序物品。 ```cpp bool compare(Item a, Item b) { double ratioA = (double)a.value / a.weight; double ratioB = (double)b.value / b.weight; return ratioA > ratioB; } ``` 3. 实现贪心算法来选择物品并装满背包。首先,将物品按照价值密度从大到小排序。然后,从价值密度最高的物品开始,依次将物品放入背包,直到背包装满或没有物品可选。 ```cpp double knapsackGreedy(vector<Item>& items, int capacity) { sort(items.begin(), items.end(), compare); double totalValue = 0.0; int currentWeight = 0; for (int i = 0; i < items.size(); i++) { if (currentWeight + items[i].weight <= capacity) { currentWeight += items[i].weight; totalValue += items[i].value; } else { int remainingCapacity = capacity - currentWeight; totalValue += (double)remainingCapacity / items[i].weight * items[i].value; break; } } return totalValue; } ``` 4. 创建一个测试函数来验证贪心算法的正确性。 ```cpp void testKnapsackGreedy() { vector<Item> items = {{10, 60}, {20, 100}, {30, 120}}; int capacity = 50; double maxValue = knapsackGreedy(items, capacity); cout << "Max value: " << maxValue << endl; } ``` 5. 调用测试函数来运行贪心算法。 ```cpp int main() { testKnapsackGreedy(); return 0; } ``` 这样就可以使用贪心算法解决C++背包问题了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值