动态规划法可以完美解决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背包最优解这个问题呢?且听下回分解。。。