贪心法——背包问题【通俗易懂】

贪心法——背包问题

今天总结了一下算法问题中的贪心法,用了一个背包问题的例子,希望可以巩固一下自己学到的知识。

一、概述
贪心法把一个复杂问题分解为一系列较为简单的局部最优选择,每一步选择都是对当前的一个扩展,直到获得问题的完整解。

二、适用范围
典型应用是求解最优化问题,而且对许多问题都能得到整体最优解。
注意:由于贪心法并不是从整体最优考虑,它所做出的选择只是在某种意义上的局部最优,这种局部最优选择并不总获得整体最优解,但通常能获得近似最优解。

三、背包问题

【问题】
给定n个物品和一个容量为C的背包,物品i的重量是wi,其价值为vi,背包问题是如何选择装入背包中物品的总价值最大。

【分析】
在贪心算法中,背包问题可以有三种思路,
第一种就是直接按照物品的价值,从价值最大的开始往背包里面装,直到达到背包容量。
第二种就是直接按照物品的重量,从重量最小的开始往背包里面装,直到达到背包容量。
显然上面的两种办法都没有能力满足背包问题的最优解,因为它只是单方面的考虑的价值的增长或容量的消耗,其实最好的想法是按照单位重量的价值,往背包里面装物品。这个是比较合理的一个做法。

【算法】
设背包容量为C,且共有n个物品,物品重量存放在数组w[n]中,价值存放在数组v[n]中,问题的解存放在数组x[n]中。
第一步要做的事情是按照单位重量价值v[i]/w[i]降序排列。这里使用了一个冒泡排序:

#include<stdio.h>
int main(){
int a[10];
int i,j,t;
for(i=0;i<10;i++)
{
scanf("%d",&a[i]);
}
for(i=1;i<10;i++)     
for(j=0;j<10-i;j++)    //比较一轮将一个较大的数沉底
if(a[j]>a[j+1])       // 两两进行比较,降序是 < 升序是 >
 {
 t=a[j];a[j]=a[j+1];a[j+1]=t;
 }
    for(i=9;i>=0;i--)
    printf("%4d",a[i]);
    return 0;
}

第二步就是将获得的解的数组x[n]初始化为0;并且按照下面的代码进行循环,往背包里面装东西,直到要装进去的物品的w[i]超过了背包的剩余容量。

int x[n] = {0};
int maxValues = 0;  //装入背包的物品的总价值
int i;
    for( i=0 ;w[i]<C;i++)
    {
        x[i] = 1;    //说明第i+1个物品放入到背包
        maxValue += v[i];
        C = C - w[i]; 
    }

第三步就是将背包剩余的容量装满,虽然它可能装不下一整个物品。

x[i] =(double) C/w[i];    //第i+1个物品装入的比例
    maxValue += x[i]*v[i];   //装入背包的物品的总价值

贪心法背包问题的C++代码:

#include<iostream>
using namespace std;
int KnapSack(int w[],int v[], int count,int C){
    double x[10] ={0} ;
    int maxValue = 0;

    for(int j = 1;j<count;j++){
        for(int i = 0;i<count-j;i++)
        {
        double temp;
        double t1 = v[i]/w[i];
        double t2 = v[i+1]/w[i+1];  

        if(t1<t2){
            temp = v[i];v[i]=v[i+1];v[i+1]=temp;
            temp = w[i];w[i]=w[i+1];w[i+1]=temp;
                 }    

        }

    } 
    for(int i=0;i<3;i++)    //展示一下排序结果
    {     
        cout<<"w["<<i<<"] :"<<w[i]<<"  "<<"v["<<i<<"]  :"<<v[i]<<endl;
    }
    int i;
    for( i=0 ;w[i]<C;i++)
    {
        x[i] = 1;
        maxValue += v[i];
        C = C - w[i]; 
    }
    x[i] =(double) C/w[i];
    maxValue += x[i]*v[i];
    return maxValue;
}

int main(){
    int w[3]= {20,30,10};
    int v[3]= {60,120,50};
    int c= 50;
    int value;
    value =KnapSack(w,v,3,c);
    cout<<value<<endl;
    return 0;
}
  • 7
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值