背包问题求解原理:
为了装满背包,我们导出一个递归公式如下,设V[i,j]用来表示从前i项中取出来的装人体积为j的背包的物品的最大价值。这里,i的范围是从О到n,j的范围是从0到C。这样,要寻求的是值 V[n,C]。很清楚,V[o,j]对于所有j的值是0,这是由于背包中什么也没有。另-方面,V[i,0]对于所有i的值为0,因为没有东西可放到为0的背包里。一般情况下,当i和j都大于0时,有下面的结论,它是很容易证明的。
观察结论
1.V[i-1,j]:仅用最优的方法取自的物品去装入体积为j的背包所得到的价值最大值。
2. V[i-1,j- s,]+n:用最优的方法取自的物品去装入体积为j- s;的背包所得到的价值最大值加上物品u;的价值。这仅应用于如果j≥s、以及它等于把物品u加到背包上的情况。
背包问题的递推公式:
(CSDN导入不了word上写的公式,只能放图片,难受,呜呜┭┮﹏┭┮)
背包容量为10
有4个物品
这四个物品的体积与价值分别为:
2 4 第一件物品
3 2 第二件物品
4 5 第三件物品
6 8 第四件物品
前n件物品的体积相加应小于等于相应的容量,并在该容量下使相应的价值相加实现最大。
0 1 2 3 4 5 6 7 8 9 10 //0~10不同容量下分别能装下不同体积的物品
0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 4 4 4 4 4 4 4 4 4
2 0 0 4 4 4 6 6 6 6 6 6
3 0 0 4 4 5 6 9 9 9 11 11
4 0 0 4 4 5 6 9 9 12 12 13
如上图矩阵
【3,6】指的是前三件物品在容量为6时,实现的最大价值,此时第一件物品与第三件物品的体积相加,价值也相加,此时为5+4=9,虽然容量为6的情况下也可以装下第一件与第二件物品,但这两件物品的价值为4+2=6,没有前者的价值大,所以将9放进,实现该容量下的最大价值。
【4,9】指的是前4件物品在容量为9时,实现的最大价值,此时为第一件和第四件物品的体积相加,虽然不能完全装完背包但此时的价值8+4=12相加最大。在容量为9的情况下,也可以装下第一件、第二件和第三件物品,但这些物品的价值相加为4+2+5=11,12>11所以还是装12,实现该容量下的最大价值。
代码实现如下:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
void pack01();
int max(int a,int b);
int main()
{
pack01();
return 0;
}
int max(int a,int b)
{
return a>b?a:b;
}
void pack01()
{
int *w;
int *v;
int i,j,n,c;
printf("输入背包容量以及物品个数(容量 个数):");
scanf("%d%d",&c,&n);
printf("输入各个物品体积以及价值(体积 价值(回车)):\n");
w=(int* )malloc(n*sizeof(int));
v=(int* )malloc(n*sizeof(int));
w[0]=v[0]=0;
for(i=1;i<n+1;i++){
scanf("%d%d",&w[i],&v[i]);
}
int dp[n+1][c+1];
for(i=0;i<=n;i++)
dp[i][0]=0;
for(j=0;j<=c;j++)
dp[0][j]=0;
for(i=1;i<=n;i++)
for(j=1;j<=c;j++)
{
dp[i][j]=dp[i-1][j];
if(w[i]<=j)
dp[i][j]=max(dp[i][j],dp[i-1][j-w[i]]+v[i]);
}
for(i=1;i<=n;i++)
{
for(j=1;j<=c;j++)
{
printf("%d\t",dp[i][j]);
}
printf("\n");
}
printf("\n%d\n",dp[n][c]);
printf("按任意键继续\n");
}
程序实现: