Day_29,贪心算法(详细描述及0-1背包问题/分数背包)

1、贪心算法的设计过程
2、如何证明贪心算法能否求解一个最优化问题
3、0-1背包问题/分数背包

贪心算法的设计过程

动态规划算法已在上篇文章中阐述并且使用了 动态规划及贪心算法求解活动选择,下面将分析是如何设计贪婪算法的,将通过下面5个点来说明,上篇文章就是按照下述方法实现贪心算法的。

1.确定最优子结构
2.设计递归算法
3.做出贪心选择
4.证明贪心选择是安全的(不影响最优子结构)
5.做一个迭代算法求出最优活动选择

按照上面顺序对应到活动选择,分别是
1.最优子结构: c[i,j] = c[i,k]+c[k,j]+1
2.递归算法: c[i,j] = max(c[i,j],c[i,k]+c[k,j]+1)
3.贪心选择: 选择最早结束的活动,如上篇文章中的贪心运行代码
4.证明贪心选择是安全的: 如上篇文章中的定理16.1的证明(其实稍微理解一下也能够判断得出是正确的┑( ̄Д  ̄)┍)
5.贪心的迭代算法: A=A∪ak,S[ak]≥F[Alast],其中A是选择出来的活动集,S是开始时间,F是结束时间

上述步骤可以简化成下面三个步骤:
1.最优化问题做出一次选择之后,只剩下一个子问题需要求解
2.证明贪心选择是安全的
3.做出贪心选择之后,最优解与贪心选择组合可以得到原问题的最优解,即得到最优子结构

按照上面顺序对应到活动选择,分别是
1.由原本的 c[i,j] = max(c[i,j],c[i,k]+c[k,j]+1) 需要考察所有的选择(i~j的所有组合),变成只需要考虑 哪个活动最早结束
2.如上篇文章中的定理16.1的证明(其实稍微理解一下也能够判断得出是正确的┑( ̄Д  ̄)┍)
3.A=A∪ak,S[ak]≥F[Alast]

虽然步骤简化了,但是要始终记得,在每一个贪心算法背后,都有一个更复杂的动态规划

如何证明贪心算法能否求解一个最优化问题

有两个要素: 贪心选择性质最优子结构
上面这两个要素并不能确定贪心算法一定能解决最优化问题,但是没有一定不能。
贪心选择性质: 可以通过做出局部最优选择来构造全局最优解。👈这个很重要,没有的话不能用贪心算法哦 也就是说,我们不需要考虑子问题的解,只需要做出当时看起来是最好的选择。
最优子结构: 同动态规划,即一个问题的最优解包含其子问题的最优解,我们则称他有最优子结构。

贪心选择和动态规划的适用问题类型

动态规划和贪心选择都有着最优子结构,那他们又有何区别呢?看下面两个问题
在这里插入图片描述
现在假设含有这样两个情况
“商品1: 60RMB,重10kg;商品2: 100RMB,重20kg;商品1: 120RMB,30kg;”
“金沙: 60RMB,重10kg;银沙: 100RMB,重20kg;铜沙: 120RMB,30kg;”

上述两个问题是不是很像!他们都有着最优子结构,但是他们
0-1背包问题: 能使用动态规划算法,但是不能使用贪心算法。
咱们来思考一下,如果咱们用贪心算法,那他贪心的核心是什么呢?
拿价值最高的东西?可能背包装不满导致价值非最大
拿最多的东西?价值高的东西难道不香吗?
分数背包问题: 贪心算法,当然也就可以用动态规划的方法

下面分别给出上面两个问题对应的代码:
//dp[i][w]表示0~i-1个物品中选择出来的最大价值,背包剩余承重为w
//第i个物品我们有两种状态,选和不选
//不选的话问题变成: dp[i-1][w] ,即背包剩余承重不变
//选的话问题变成: dp[i-1][w-wi] ,即背包剩余承重少了wi
//所以状态方程就是: dp[i][w] = max(dp[i-1][w-wi]+vi ,dp[i-1][w])
//即dp[i][w] = max(dp[i-1][w–weight[i-1]]+vi ,dp[i-1][w])
0-1背包问题:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <vector>
using namespace std;

int zeroOneBag(int *value,int *weight,int bagCap,int num)
{
    vector<vector<int>> dp(num+1,vector<int>(bagCap+1));
    for (int i=0;i<bagCap;i++)
    {
        dp[0][i]=0;
    }
    for (int i=0;i<num;i++)
    {
        dp[i][0]=0;
    }
    for (int i=1;i<=num;i++)
        for (int w=1;w<=bagCap;w++)
            if (weight[i]>w)
                dp[i][w] = dp[i-1][w];
            else
                dp[i][w] = max(dp[i-1][w],dp[i-1][w-weight[i]]+value[i]);
    return dp[num][bagCap];
}

int main()
{
    int value[3] = {60,100,120};
    int weight[3] = {10,20,30};
    int bagCapacity = 50;
    int result = zeroOneBag(value,weight,bagCapacity,sizeof(value)/sizeof(*value));
    cout<<result;
}

运行结果如下

// 拿均价尽量高的物品
分数背包问题:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <vector>
using namespace std;

int fractionBag(int *value,int *weight,int bagCap,int num)
{
    int totalValue = 0;
    int tempCap = 0;
    int ave[num]={};
    for (int i=0;i<num &&tempCap<bagCap;i++)
        if (weight[i]+tempCap<=bagCap)
        {
            totalValue+= value[i];
            tempCap+= weight[i];
        }
        else
        {
            totalValue+= (bagCap-tempCap)*(value[i]/weight[i]);
            tempCap+= bagCap-tempCap;
        }
    return totalValue;
}

int main()
{
    int value[3] = {60,100,120};
    int weight[3] = {10,20,30};
    int bagCapacity = 50;
    int result = fractionBag(value,weight,bagCapacity,sizeof(value)/sizeof(*value));
    cout<<result;
}

在这里插入图片描述

结文鸡汤:真正的实力不是体现在你状态好的时候能做到100分,而是在你状态不佳的时候也能做到100分((╯‵□′)╯︵┻━┻,说状态不好都是接口!)

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: surf_cli_chn_mul_day-tem-12001-201501.txt是一个文件名,这个文件可能是一个文本文件。根据文件名的后缀“txt”可以判断出这是一个文本文件。根据文件名中的其他信息,可以猜测这个文件记录了2015年1月份中国地区某个地点的多天的海浪信息和气温信息。 文件名中的“surf_cli_chn_mul_day”可能表示这是一个关于冲浪、气象和中国的多天数据文件。其中“surf”可能指的是冲浪,意味着这个文件中包含有关冲浪条件和海浪高度的数据。而“cli”可能表示气候或气象,意味着这个文件中可能还包含了一些与气温或其他气象要素相关的数据。最后,“chn_mul_day”可能表示这是中国地区多天的数据,指的是这个文件中包含了多天的数据,可能是按日期顺序排列。 根据文件名中的“tem-12001-201501”部分,可以猜测这个文件可能是关于2015年1月份某个地点的气温数据。其中“tem”可能表示气温,而“12001”可能是指某个具体地点的编号或代号。而“201501”则代表了这个文件中记录的是2015年1月份的数据。 总结而言,surf_cli_chn_mul_day-tem-12001-201501.txt这个文件名暗示了这是一个包含了中国某地2015年1月份多天的冲浪和气温数据的文本文件。 ### 回答2: surf_cli_chn_mul_day-tem-12001-201501.txt是一个文件名,它可能表示一个气象数据文件。根据文件名的命名规则,该文件可能包含2015年1月份中国某个城市或地区的多日气温数据。 在该文件中,"surf_cli_chn_mul_day"可能代表"surface climate China multiple day"(中国地面气候多日)的缩写,意味着这是一个包含中国地面气候数据的文件。"tem"可能代表"temperature"(温度),表示该文件中包含的是温度数据。"12001"可能是文件的编号,用于标识该文件属于某个特定的数据集或项目。"201501"代表文件所涵盖的日期范围,可能是2015年1月。 由于题目只提供了文件名,并未提供具体的内容或其他背景信息,因此对于该文件的具体内容和用途,我无法做更详细的解读。要了解更多关于该文件的信息,需要查阅实际的文件内容或者咨询相关的数据提供机构或个人。 ### 回答3: surf_cli_chn_mul_day-tem-12001-201501.txt 是一个文件名,文件中可能包含有关2015年1月份中国多地的冷暖气温数据。 根据文件名可以分析出以下信息: 首先,文件是以“surf_cli_chn_mul_day-tem-12001-”开头的,这可能表示了该文件是多个城市的气温数据。 然后,文件名中的“201501”表示了该文件记录的是2015年1月份的数据。 如果我们打开这个文件,可能会看到以下内容: 该文件可能包含有关中国多个城市在2015年1月份每天的气温数据。这些数据可能以一定的格式来展示,可能按照城市和日期进行分组,并且可能有时间间隔。 该文件可能是一个纯文本文件,我们可以使用文本编辑器来打开它,并查看其中的内容。在文件中,每个城市的气温数据可能以一定的形式被记录,常见的格式可能是每行记录一个数据点,包括城市、日期和相应的气温值。 通过分析该文件,我们可以获得2015年1月份中国多地的气温趋势,可以观察各个城市在这个月份内的气温变化情况,从而对该时期的气候有更多的了解。这些数据对于气象研究、城市规划以及农业生产等领域可能具有重要的参考价值。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值