动态规划法和贪心法解决0/1背包问题的差别(1)

来源:互联网 发布:值乎app 官网 编辑:程序博客网 时间:2024/05/16 07:06

动态规划法可以完美解决0/1背包问题,得到最优解。而贪心法通过单位重量价值量排序策略  解决0/1背包问题时  不一定达到全局最优。

下面是动态规划法解决0/1背包问题的代码(c++实现):

#include<iostream>
using namespace std;
template <typename T>
T max(T a,T b)
{  
        if(a<b)
            a=b;
         return   a;
}
int c;//
背包容量
int knapsack(int n,int w[],int v[]);//
声明建立二维表格的函数
int **p=NULL;//
声明指向二维表格的二维指针
int *x=NULL;//
决策数组指针
int main()

 int n;//
物品数目
int m;//
最大价值
int *w=new int [n];//
重量动态数组的分配
int *v=new int [n];//
价值动态数组的分配
cout<<"
请输入物品数目:";
cin>>n;
cout<<endl;
cout<<"
请输入背包容量:";
cin>>c;
p=new int *[n+1];
for(int i=0;i<=n;i++)
{
         p[i]=newint[c+1];
}//
动态二维数组的分配
x=new int [n];//
动态决策数组的分配*/
for(int j=0;j<n;j++)
{
cout<<"
输入"<<j+1<<"物品的重量:";
cin>>w[j];
cout<<"价值:";
cin>>v[j];
cout<<endl;
}
m=knapsack(n,w,v);//
调用
cout<<"
最大价值为"<<m<<endl;
for(int k=0;k<n;k++)
{
cout<<x[k]<<endl;
}
 if(p)  
    {  
        //
删除申请的内存  
        for(int i = 0; i < n; i++)  
        {  
            delete []p[i];  
        }  
        delete [] p;  
    }  
delete[] x;//删除申请的内存 
delete[] w;//删除申请的内存 
delete[] v;//
删除申请的内存 
 system("pause");  
return 0;
}
int knapsack(int n,int w[],int v[])
{
    
   for(int i=0;i<=n;i++)
     p[i][0]=0;
   for(int j=0;j<=c;j++)
     p[0][j]=0;
for(i=1;i<=n;i++)
   for(j=1;j<=c;j++)
      if(j<w[i-1])
        p[i][j]=p[i-1][j];
      else
        p[i][j]=max(p[i-1][j],p[i-1][j-w[i-1]]+v[i-1]);
      j=c;
   for(i=n;i>0;i--)
   {
    if(p[i][j]>p[i-1][j])
         {
    x[i-1]=1;
   j=j-w[i-1];
         }
  else
   x[i-1]=0;
   }
return p[n][c];
}    //
按书上抄的


贪心法通过单位重量价值量排序策略  解决0/1背包问题的代码(换换口味,c语言实现):

#include <stdio.h>  
int M; 
struct node{ 
  float value; 
  float weight; 
  float flag; //
标志位
}temp; 
struct node *Node=new node [M];
float curvalue=0; 
float Weight,curweight=0; 
float flag;
void sort(){ 
     int i,j; 
     for(i=0;i<M-1;i++){ 
         for(j=i+1;j<M;j++){ 
            if((Node[i].value/Node[i].weight)<(Node[j].value/Node[j].weight)){ 
                temp=Node[i]; 
                Node[i]=Node[j]; 
                Node[j]=temp; 
             } 
         } 
     } 
} //
冒泡法排序,读者可用效率更高的快速排序
 
//
装载主要方法  
void load(){ 
    int i; 
    for(i=0;i<M;i++)
       { if((Node[i].weight+curweight)<=Weight)

         {

             curvalue+=Node[i].value; 
             curweight+=Node[i].weight; 
             Node[i].flag=1; 
         }

         else
       {Node[i].flag=0; }
         } 
                   } 
 
//
进行结果的输出  
void putout(){ 
    int i; 
    printf("
选中物品的重量分别为:"); 
    for(i=0;i<M;i++){ 
        if(Node[i].flag){ 
          printf("%.2f",Node[i].weight);               
        } 
    } 
         printf("\n
总价值为:%.2f",curvalue); 

int main(){ 
          int i;   
         printf("
输入物品个数:\n");
         scanf("%d",&M);
    printf("
请输入物品的重量和价值:\n"); 
    for(i=0;i<M;i++){ 
        Node[i].flag=0.0;
       printf("
请输入第%d个物品的重量和价值",i+1); 
       scanf("%f%f",&Node[i].weight,&Node[i].value); 
    } 
    printf("\n
请输入背包容积:"); 
    scanf("%f",&Weight); 
    sort(); 
    load(); 
    putout(); 
  return 0; 


同样的四个物品,可以发现,用动态规划法可以达到最优解,取得最大价值8,而用贪心法(单位重量价值排序策略)只能取得价值5

这是为什么呢??

                 稍加思考,我们就可以找到原因,贪心法解决0/1背包时压根没把背包装满。而贪心法(单位重量价值排序策略)能取得背包问题的最优解正是因为可以装满背包。

                 如何解决贪心法(单位重量价值排序策略)不一定取得0/1背包最优解这个问题呢?且听下回分解。。。




0 0