1. 程式人生 > >貪心法——揹包問題【通俗易懂】

貪心法——揹包問題【通俗易懂】

貪心法——揹包問題

今天總結了一下演算法問題中的貪心法,用了一個揹包問題的例子,希望可以鞏固一下自己學到的知識。

一、概述
貪心法把一個複雜問題分解為一系列較為簡單的區域性最優選擇,每一步選擇都是對當前的一個擴充套件,直到獲得問題的完整解。

二、適用範圍
典型應用是求解最優化問題,而且對許多問題都能得到整體最優解。
注意:由於貪心法並不是從整體最優考慮,它所做出的選擇只是在某種意義上的區域性最優,這種區域性最優選擇並不總獲得整體最優解,但通常能獲得近似最優解。

三、揹包問題

【問題】
給定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;
}