贪心算法

贪心算法又叫贪娈算法,在求解问题时,总是求解在当前看来最优的解,通俗一点讲就是,贪心算法所做出的选择是局部最优选择,所以贪心算法并不是对所有的问题都能得到整体最优选择,应用范围很广泛,所以贪心算法所得到的选择是整体最优选择或整体最优选择的近似解。

例题分析
[0-1背包问题]有一个背包,背包容量是M=150。有7个物品,物品不可以分割成任意大小。

要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。

物品 A B C D E F G

重量 35 30 60 50 40 15 20

价值 10 40 30 50 35 40 30

根据贪心选择,最优解可能有三种情况:
1.每次装价值最高的物品
2.每次装重量最大的物品
3.每次装性价比(单位重量的价值:value/weight)最高的物品

根据题目意思,要尽可能的在书包的承受能力之内使总价值最大。

⑴贪心策略:选取价值最大者。

反例:

W=50

物品:A B C

重量:45 25 20

价值:30 20 20

根据策略,首先选取物品A,接下来就无法再选取了,可是,选取B、C则更好。

⑵贪心策略:选取重量最小。
反例:

W=50

物品:A B C

重量:50 25 20

价值:45 20 15
根据策略,首先选取物品B,接下来就是C,可是,选择A则是更好。

⑶贪心策略:选取单位重量价值最大的物品。

反例:

W=30

物品:A B C

重量:28 20 10

价值:28 20 10

根据策略,三种物品单位重量价值一样,程序无法依据现有策略作出判断,如果选择A,则答案错误。

【注意:如果物品可以分割为任意大小,那么策略3可得最优解】
为什么这么说呢?答案很简单,先按照性价比来,然后剩下的把性价比高的再分割,直到背包装满。

#include <iostream>  
using namespace std;  

struct Node  
{  
    float weight;  
    float value;  
    bool mark;//标志  
    char char_mark;//物品的字母标号ABCD……  
    float pre_weight_value;//单价(性价比)
};  

int main()  
{  
    float Weight[7] = {35,30,60,50,40,15,20};  
    float Value [7] = {10,40,30,50,35,40,30};  
    Node array[7];  
    for(int i=0; i<7; i++)  
    {  
        array[i].value = Value[i];  
        array[i].weight = Weight[i];  
        array[i].char_mark = 65 + i;//七个物品分别给出字母标号ABCDEFG  
        array[i].mark = false;//初始化false,表示现在所有物品都还没装进去  
        array[i].pre_weight_value = Value[i] / Weight[i];//单价  
    }  
    cout<<"每个物品的单价为:"<<endl;  
    for(int i=0;i<7;i++)  
        cout<<array[i].char_mark<<":"<<array[i].pre_weight_value<<endl;  
    cout<<endl;  

    float weight_all=0.0;  
    float value_all = 0.0;  
    float max = 0.0;  
    char charArray[7];  
    int flag,n = 0;  
    int count = 0;//计数,当装进去一个物品就自加1
   while(weight_all < 150)  
    {  
        for(int index=0;index < 7; ++index)//循环找出目前性价比最高的且还没装进去的物品,并且找出下标 
        {  
            if(array[index].pre_weight_value > max && array[index].mark == false)   
            {  
                max = array[index].pre_weight_value ;  
                flag = index;  
            }  
        }  

        charArray[n++] = array[flag].char_mark;//array[flag].char_mark是上面循环中找出的的字母标号  
        array[flag].mark = true;//true表示把该物品装进去 
        count++;
        weight_all += array[flag].weight;  
        value_all += array[flag].value;  
        max = 0.0;//此处的max==0很重要
        if(weight_all > 150)//用于判断刚刚把物品加进去会不会超过背包承载能力,
            //如果超过了,就把该物品拿出来
        {
            weight_all -= array[flag].weight;  
            value_all -= array[flag].value; 
            n--;//此处很重要
        }
        if(count == 7)//count表示7,即每个物品都已经判断装过了(有的由于超过背包承载力会被拿出来)

            break;//然后跳出循环

    }  
    cout<<"装入的物品为:"<<endl;  
    for(int i=0;i<n;i++)  
        cout<<charArray[i]<<" ";  
    cout<<endl;  
    cout<<"weight_all:"<<weight_all<<endl;  
    cout<<"value_all:"<<value_all<<endl;  

    system("pause");  
    return 0;  
} 

运行截图这里写图片描述

以此来纪念我的第一篇bolg。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值