0-1背包问题
0-1背包问题是典型的动态规划问题,看了好多博客和书面教材,一直是似懂非懂的感觉,自从看了一部教学视频以后,感觉恍然大悟,讲的确实非常通俗易懂,而且有写代码的过程,非常推荐!!
http://www.tudou.com/listplay/Z-bWgybEtig/XaOy3xM2klU.html
其实0-1背包问题可以抽象成一个小偷拿着一个容量有限(容量设为W)的背包去商店偷东西,每个商品都有自己的体积w和价值v,小偷的目的就是用这个容量有限的背包装满价值总量最大的东西。
为了讨论方便,我们限定一个具体的背景,不妨设背包容量W=20,
要偷的东西的体积w和价值v分别如下:
商品名称k | 体积w | 价值v |
0 |
2 |
3 |
1 | 3 | 4 |
2 | 4 | 5 |
3 | 5 | 8 |
4 | 9 | 10 |
当计算完B(0,2)时,按原路返回,最后得到B(4,20)。
下表是0-1背包解题过程表,可以用来记录每一步的计算过程。
#include<stdio.h> int n,c,bestp;//物品的个数,背包的容量,最大价值 int p[10000],w[10000],x[10000],bestx[10000];//物品的价值,物品的重量,x[i]暂存物品的选中情况,物品的选中情况 void Backtrack(int i,int cp,int cw) { //cw当前包内物品重量,cp当前包内物品价值 int j; if(i>n)//回溯结束 { if(cp>bestp) { bestp=cp; for(i=0;i<=n;i++) bestx[i]=x[i]; } } else for(j=0;j<=1;j++) { x[i]=j; if(cw+x[i]*w[i]<=c) { cw+=w[i]*x[i]; cp+=p[i]*x[i]; Backtrack(i+1,cp,cw); cw-=w[i]*x[i]; cp-=p[i]*x[i]; } } } int main() { int i; bestp=0; printf("请输入背包最大容量:\n"); scanf("%d",&c); printf("请输入物品个数:\n"); scanf("%d",&n); printf("请依次输入物品的重量:\n"); for(i=1;i<=n;i++) scanf("%d",&w[i]); printf("请依次输入物品的价值:\n"); for(i=1;i<=n;i++) scanf("%d",&p[i]); Backtrack(1,0,0); printf("最大价值为:\n"); printf("%d\n",bestp); printf("被选中的物品依次是(0表示未选中,1表示选中)\n"); for(i=1;i<=n;i++) printf("%d ",bestx[i]); printf("\n"); return 0; }
程序运行结果如下:
与计算表格的右下角的值一样,同为26,说明计算正确!
向代码最深处出发~!