背包问题的贪心算法

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<<"#####背包问题的贪心算法##### "<<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背包问题。

原文地址:https://www.cnblogs.com/leftshine/p/5698549.html