贪心问题

贪心

贪心:把整体问题分解成多个步骤,在每个步骤都选取当前步骤的最优方案,直到所有步骤结束;每个步骤不会影响后续步骤。
核心性质:每次采用局部最优,最终结果就全局最优。
如果题目满足上述核心性质,则可用贪心求解。

例:最少钱币支付问题

假设有三种钱币:1元、2元、5元,数量不限,现在需支付m元,要求钱币数目最少,应如何支付?
局部最优:要保证硬币尽可能少,所以当前尽可能选择大面值硬币
此问题只要采用局部最优就能得到全局最优

如果把钱币面值改成1元、2元、4元、5元、6元,现需支付9元,按贪心方法:6+2+1需要3个币
但是最优结果:4+5

那么如何判断是否能用贪心?
1、最优子结构性质:
当一个问题的最优解包含子问题的最优解,则称之为具有最优子结构性质。
2、贪心性质选择:可以通过局部最优的选择得到全局最优
具体问题怎么做?
1、经验积累各种类型的贪心问题
2、举反例

经典贪心问题

532纪念品分组

题目链接:532纪念品分组

在这里插入图片描述
每组最多两件,价值之和不超过w
尽可能不浪费空间:大的和小的凑在一起

w = int(input())
n = int(input())
a = []
for i in range(n):
    a.append(int(input()))

a.sort()

ans = 0
l , r = 0 , n - 1
while True:
    #如果l、r相等说明只剩下一个元素,将其加入答案并跳出循环
    if l == r :
        ans += 1
        break
    #如果l大于r,说明遍历完成跳出循环
    if l > r:
        break
    #如果 a[l] + a[r] <= w,说明当前指向的两个元素的和小于等于w,将l右移一位,r左移一位,答案加1
    if a[l] + a[r] <= w:
        l += 1
        r -= 1
        ans += 1
    else:#否则,r左移一位,答案加1
        r -= 1
        ans += 1
print(ans)
100
9
90
20
20
30
50
60
70
80
90

6

209翻硬币

题目链接:209翻硬币
在这里插入图片描述

s = list(input())
t = list(input())
n = len(s)
ans = 0
for i in range(n-1):
    if s[i] != t[i]:
        ans += 1
        if s[i+1] == '*':
            s[i+1] = 'o'
print(ans)
**********
o****o****
5
好的,背包问题是一个经典的动态规划问题,但也可以使用贪心算法来解决。下面是使用贪心算法解决背包问题的JAVA代码: ```java import java.util.Arrays; public class KnapsackProblem { public static void main(String[] args) { int[] weight = {10, 20, 30}; // 物品重量 int[] value = {60, 100, 120}; // 物品价值 int capacity = 50; // 背包容量 double maxValue = getMaxValue(weight, value, capacity); System.out.println("背包能装的最大价值为:" + maxValue); } /** * 获取背包能装的最大价值 * @param weight 物品重量 * @param value 物品价值 * @param capacity 背包容量 * @return 背包能装的最大价值 */ public static double getMaxValue(int[] weight, int[] value, int capacity) { int n = weight.length; double[] unitValue = new double[n]; // 单位价值 for (int i = 0; i < n; i++) { unitValue[i] = (double) value[i] / weight[i]; } int[] index = new int[n]; // 物品索引 for (int i = 0; i < n; i++) { index[i] = i; } Arrays.sort(index, (i, j) -> Double.compare(unitValue[j], unitValue[i])); // 按单位价值从大到小排序 double maxValue = 0; // 背包能装的最大价值 for (int i = 0; i < n && capacity > 0; i++) { int j = index[i]; double w = Math.min(weight[j], capacity); // 能装下的重量 maxValue += w * unitValue[j]; // 能装下的最大价值 capacity -= w; } return maxValue; } } ``` 在这个代码中,我们计算每个物品的单位价值,并按照单位价值从大到小排序,然后依次选择单位价值最大的物品放入背包中,直到背包无法再装下物品为止。 这里使用了lambda表达式来简化排序过程,如果不理解可以使用传统的Comparator或Comparable来进行排序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

唐丶晚笙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值