背包問題的貪心算法


1. 貪心算法的基本原理:

貪心算法總是作出在當前看來最好的選擇。也就是說貪心算法並不從整體最優考慮,它所作出的選擇只是在某種意義上的局部最優選擇。當然,希望貪心算法得到的最終結果也是整體最優的。雖然貪心算法不能對所有問題都得到整體最優解,但對許多問題它能產生整體最優解。如單源最短路經問題,最小生成樹問題等。在一些情況下,即使貪心算法不能得到整體最優解,其最終結果卻是最優解的很好近似。 

貪心算法求解的問題一般具有兩個重要性質:貪心選擇性質和最優子結構性質。

(1)所謂貪心選擇性質是指所求問題的整體最優解可以通過一系列局部最優解的選擇,即貪心選擇來達到。這是貪心算法可行的第一個基本要素,也是貪心算法與動態規划算法的主要區別。

(2)當一個問題的最優解包含其子問題的最優解時,稱此問題具有最優子結構性質。問題的最優子結構性質是該問題可用動態規划算法或貪心算法求解的關鍵特征。

2)背包問題的貪心算法實現

算法實現主要代碼如下:

#include <iostream.h>

#include <string>

#include <conio.h>

using namespace std;

 

//物品信息結構體

struct goodinfo

{

    float p; //物品效益

    float w; //物品重量

    float X; //物品該放的數量

    int flag; //物品編號

};

 

//*********按物品效益,重量比值做升序排列***************//

void Insertionsort(goodinfo goods[],int n)

{

    int j,i;

    for(j=2;j<=n;j++)

    {

        goods[0]=goods[j];

        i=j-1;

        while (goods[0].p>goods[i].p)

        {

            goods[i+1]=goods[i];

            i--;

        }

        goods[i+1]=goods[0];

    }

}

 

//*********將物品放入背包**************//

void bag(goodinfo goods[],float M,int n)

{

    float cu;

    int i,j;

    for(i=1;i<=n;i++)

        goods[i].X=0;

    cu=M; //背包剩余容量

    for(i=1;i<n;i++)

    {

        if(goods[i].w>cu)//當該物品重量大與剩余容量跳出

            break;

        goods[i].X=1;

        cu=cu-goods[i].w;//確定背包新的剩余容量

    }

    if(i<=n) goods[i].X=cu/goods[i].w;//該物品所要放的量

    for(j=2;j<=n;j++) /*按物品編號做降序排列*/

    {

        goods[0]=goods[j];

        i=j-1;

        while (goods[0].flag<goods[i].flag)

        {

            goods[i+1]=goods[i];

            i--;

        }

        goods[i+1]=goods[0];

    }

    cout<<"最優解為:"<<endl;

    for(i=1;i<=n;i++)

    {

        cout<<""<<i<<"件物品要放:";

        cout<<goods[i].X<<endl;

    }

}

 

//*************主函數***************//

void main()

{

    int n;

char j;

    float M;

    goodinfo *goods;//定義一個指針

    cout<<"#####背包問題的貪心算法#####\n"<<endl;

 

    while(!(j=='n'||j=='N'))

    {

        cout<<"物品的種類數量:";

        cin>>n;

        goods=new struct goodinfo [n+1];//

        cout<<"背包的最大容量:";

        cin>>M;

        cout<<endl;

        int i;

        for(i=1;i<=n;i++)

        {

            goods[i].flag=i;

            cout<<""<<i<<"件物品:"<<endl;

            cout<<"重量:";

            cin>>goods[i].w;

            cout<<"價值:";

            cin>>goods[i].p;

            goods[i].p=goods[i].p/goods[i].w;//得出物品的重量比

            cout<<endl;

        }

        Insertionsort(goods,n);

        bag(goods,M,n);

        

        cout<<endl<<"是否繼續(y/n)?"<<endl;

        j= getch();

        cout<<"---------------------"<<endl;

    }

}

編譯並運行程序。

3)算法的時間復雜性和空間復雜性

以上算法的時間復雜度和空間復雜度為O(n2),其中時間復雜度基本已經不能再優化了,但空間復雜度可以優化到O(n)

程序運行結果如下:

注意背包問題與0-1背包問題的不同,雖然這兩個問題極為相似,但背包問題可以用貪心算法求解,而對於0-1背包問題,貪心選擇算法不能得到最優解。因為在0-1背包問題的這種情況下,它無法保證最后能將背包裝滿,部分閑置的背包空間,使每公斤背包的價值降低了。動態規划算法可以有效的解0-1背包問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM