0-1背包问题详解:如何选择物品以最大化背包价值

日期: 2025-03-25 10:06:41 |浏览: 3|编号: 84367

友情提醒:信息内容由网友发布,本站并不对内容真实性负责,请自鉴内容真实性。

0-1背包问题详解:如何选择物品以最大化背包价值

0-1背包问题:给定N类型的项目和带容量C的背包,项目i的重量是Wi,其值为VI。

问:您应该如何选择要加载到背包中的项目,以使加载到背包的项目的总价值是最大的?

分析每个项目后,我们只能选择或不采取两个选项。我们不能选择加载某个项目的一部分,也不能多次加载同一项目。

解决方案:声明一个大小m [n] [c]的二维阵列。 m [i] [j]表示面对第i-the项目时可以获得的最大值,背包容量为j。然后,我们可以轻松地分析M [i] [J]的计算方法。

(1)。对于J <w [i],背包的容量不足以放下第i-phot物品,因此您只能选择不服用它。

m [i] [j] = m [i-1] [j]

(2)。对于J> = W [i],背包容量可以放下第三件项目,因此我们需要考虑是否可以从此项目中获得更大的价值。

如果服用,m [i] [j] = m [i-1] [jw [i]] + v [i]。在这里m [i-1] [jw [i]]是指当背包容量为jw [i]时,I-1项目的最大值,这相当于为i-themit腾出w [i]的空间。

如果您不接受,m [i] [j] = m [i-1] [j],与(1)相同

无论是否接受,这自然是这两种情况之间最有价值的比较。

从中,我们可以获得状态转移方程:

if(j>=w[i])
 m[i][j]=max(m[i-1][j],m[i-1][j-w[i]]+v[i]);
else
 m[i][j]=m[i-1][j];

示例:0-1背包问题。当使用动态编程算法解决0-1背包问题时,请使用二维阵列M [i] [J]存储0-1背包问题的最佳值时,当背包的剩余容量为j时,并且可选项目是i,i,i+1,...,...,n。画

值数组v = {8,10,6,3,7,2},

重量数组W = {4,6,2,2,2,5,1},

当背包容量C = 12时,相应的m [i] [J]数组。

0123456789111121112111200088888888888888888888888811010101011818181818141414141416161618182440669999999999919191924545045450545066699999999999999太体14141414141999999部。

如m[2][6],在面对第二件物品,背包容量为6时我们可以选择不拿,那么获得价值仅为第一件物品的价值8,如果拿,就要把第一件物品拿出来,放第二件物品,价值10,那我们当然是选择拿。m[2][6]=m[1][0]+10=0+10=10;依次类推,得到m[6][12]就是考虑所有物品,背包容量为C时的最大价值。
#include <iostream>
#include <cstring>
using namespace std;
 
 
const int N=15;
 
 
int main()
{
 int v[N]={0,8,10,6,3,7,2};
 int w[N]={0,4,6,2,2,5,1};
 
 
 int m[N][N];
 int n=6,c=12;
 memset(m,0,sizeof(m));
 for(int i=1;i<=n;i++)
 {
 for(int j=1;j<=c;j++)
 {
 if(j>=w[i])
 m[i][j]=max(m[i-1][j],m[i-1][j-w[i]]+v[i]);
 
 
 else
 m[i][j]=m[i-1][j];
 }
 }
 
 
 for(int i=1;i<=n;i++)
 {
 for(int j=1;j<=c;j++)
 {
 cout<<m[i][j]<<' ';
 }
 cout<<endl;
 }
 
 
 return 0;
}

在这一点上,我们可以确定可以获得的最大值,但是我们不确定选择哪些项目可以获得最大值。

启动另一个x []阵列,x [i] = 0表示不接受它,x [i] = 1表示服用它。

m [n] [c]是最佳值。如果m [n] [c] = m [n-1] [c],则表示是否有任何n个项目相同,则x [n] = 0;否则x [n] = 1。当x [n] = 0时,继续从x [n-1] [c]构建最佳解决方案;当x [n] = 1时,继续从x [n-1] [cw [i]]构建最佳解决方案。依此类推,所有最佳解决方案都可以构建。 (我真的不知道如何解释算法书的整个副本。)

void traceback()
{
 for(int i=n;i>1;i--)
 {
 if(m[i][c]==m[i-1][c])
 x[i]=0;
 else
 {
 x[i]=1;
 c-=w[i];
 }
 }
 x[1]=(m[1][c]>0)?1:0;
}

示例:工厂预计明年将有四个新项目A,B,C和D。下表显示了每个项目WK及其投资收入VK的投资金额。总投资为30万元。如何选择一个项目以最大化总回报?

项目

WK

VK

15

12

10

12

结合前两个代码

#include <iostream>
#include <cstring>
using namespace std;
 
const int N=150;
 
int v[N]={0,12,8,9,5};
int w[N]={0,15,10,12,8};
int x[N];
int m[N][N];
int c=30;
int n=4;
void traceback()
{
 for(int i=n;i>1;i--)
 {
 if(m[i][c]==m[i-1][c])
 x[i]=0;
 else
 {
 x[i]=1;
 c-=w[i];
 }
 }
 x[1]=(m[1][c]>0)?1:0;
}
 
int main()
{
 
 
 memset(m,0,sizeof(m));
 for(int i=1;i<=n;i++)
 {
 for(int j=1;j<=c;j++)
 {
 if(j>=w[i])
 m[i][j]=max(m[i-1][j],m[i-1][j-w[i]]+v[i]);
 
 else
 m[i][j]=m[i-1][j];
 }
 }/*
 for(int i=1;i<=6;i++)
 {
 for(int j=1;j<=c;j++)
 {
 cout<<m[i][j]<<' ';
 }
 cout<<endl;
 }
*/
 traceback();
 for(int i=1;i<=n;i++)
 cout<<x[i];
 return 0;
}

输出X [I]数组:0111,输出M [4] [30]:22。

结论得出结论:BCD的三个项目的总回报率最大,为220,000元。

但是,该算法只能获得一个最佳解决方案,但无法获得所有最佳解决方案。

提醒:请联系我时一定说明是从铂牛网上看到的!