0-1背包问题
问题描述
给定n种物品和一背包,物品i的重量是wi,其价值是pi,背包的容量是如何选择 装入背包中的物品总价值最大?
问题分析
记c[iJW表示前i个物品,在背包容量大小为m的情况下,最大的装载
Mo
如果不放第i件物品,那么问题就转化为前I件物品放入容量为m的背
包中”价值为如果放第i件物品,那么问题就转化为前I件物品
放入剩下的容量为的背包中”此时能获得的最大价值就是再加上 通 过放入第i件物品获得的价值p[ilo因为背包最大容量M未知。所以,我们的程序要从 1到M—个一个的试。比如,开始任选N件物品的一个。看对
应M的背包,能不能放进去,如果能放进去,并且还有多的空间,则多出來的空间里 能放N-1物品中的最大价值。从以上最大价值的构造过程中可以看出:
c (n, m) =max{c (n-l , m), c (n~l , m-w[n])+p (n)
其中c[i-l] [m]表不第i件物品不装入背包中,而c[i-l] [m-w[i]]+p[i]表不第i件 物 品 装入背包中。
伪代码:
1 ?最优彳宜 max(xl *pl +x2*p2+,, xn*pn)
int knapsack(int m, int n,int *w, int *p) bool a;
for(int i二1 ;i<=n;i++)
for(int j二1 ;j<=m;j++)
{a=p[i]+c[i-l] [j-w[i]]>c[i J ] [j] ;c[i] [j]=a?p[i]+c[i-l]:c[i ? 1] [j];
〃前者表示放i物品,后者表示不放i物品
)
else //i号物品重量大于剩余容量,不能再放i号物品c[i]D] =c[i-l]OJ;
)
return(c[n] [m]) ;//最后的值即为最优值,返回主函数
)
2?求最优 n 7L 0-1 向量(xl ,x2,x3553xn)
int getbest(int m, int n, int *w, int *p)
if (n==0)retuin 0;//递归,每次递归 n 减 1, n 为 0 时退岀 if (w[n]>m)
<
x[n]=0;
getbest (m, n-l5w, p);
else
3 & p n H31*
-muw*淫
妥巨〉
今 cludecss i o ? hv
吵 R boo -
yapsack (inf m
旷f * p
00 - a
吵前m w〉裆毬血
M5k、、x 選弗咄
w inf
n5-f *
if (w[i]<=j)
{a二讥i]+c[i-l] [j-w[i]]>c[i-l] [j] ;c[i] [j]=a?p[i]+c[i-l]:c[i-l] [j];
〃前者表示放i物品,后者表示不放i物品
)
else //i号物品重量大于剩余容量,不能再放i号物品
}
return(c[n] [m]);〃最后的值即为最优值,返回主函数
)
〃求最优n元0-1向量(xl, x2, x3……,xn)
int getbest (int mjnt n,int *w, int *p)
{
if(n==O)retuin 0;//递归,每次递归 n 减 1, n 为。时退出 if(w[n]>m)
<
x[n]=0;
getbest (m, n-1, w, p);
)
else
{
〃如果 c[n] [m]由 p[n] +c[n-1] [m-w[n]]而来,则 x[n]二 1;
〃女 口果 c[n] [m]由 c[n-l] [mJ]而来贝 S x[n]=0;
[n]=c[n-l ] [m]〈二p[n]+c [n-l ] Lm-w[n]];
if (x.nl)
getbest(m-wEn], n~l , w, p);
else getbest (m, n-1, w, p);
)
)
void mainO
int m, n;
int 佔NULL;
int *p=NULL;
printfC输入背包容量和货物个数「);
scanf (n%d%d'' ;&m, &n);
P=(int *)calloc(n, sizeof (int)) ; n 分配 n*sizeof (int)的内存大小,存取 n 个物品的 价 格w=(int *)calloc(n, sizeof (int)) ; n分酉己n*sizeof (int)的内存大小,存取n个物品 的质 量if(!p|| !w)//检测分配是否成功
printf ("Not Enough Memory! \nk);
exit ⑴;//分配失败,退出
for(int i二1 ;i
printf (M 物品 x%d 的重量和价值i) ; scanf (a%d%d^, w+i5p+i);
pri