赞
踩
首先让我们回顾一下动态规划法的使用规则:
1、划分子问题:将元问题分解为若干个子问题,每一个子问题对应一个决策,并且子问题之间具有重叠关系
2、确定动态规划函数:根据子问题之间的重叠关系找到子问题满足的递归关系式(即动态规划函数),这是实现思路的关键。
3、填写表格:设计表格,自下而上的方式计算各个子问题的解并填表,实现动态规划过程。
给定n中物品和一个背包,物品i(1<=i<=n)的重量是wi,其价值为vi,背包容量为C,对每种物品只有两种选择:装入背包或不装入背包,如何选择装入背包的物品,是的装入背包的总价值最大?
解题思路:
是不是有点绕,来解释一波:
1、背包容量不足:当我们背包的容量不够的情况下,肯定是不能装入的,这思路很清晰,所以这个时候表示V(i,j)的价值和V(i-1,j)的价值一样,因为第 i 个没有放入。
2、背包容量足够:这时候肯定有人要问了,既然背包容量都足够放第 i 个,为啥不放进去呢?还会有不放入的情况呢?只要是放入价值肯定更大啊?我的解释:当我们将第 i 物品装入不一定达到当前最优解,应当在即V(i,j)=max{V(i-1,j),V(i-1,j-w(i))+v(i)}中选出最优的解!如果前者更大:表示这第 i 个物品没有加入,如果后者更大:表示装入了第 i 个!
2、如果还没有理解透彻,我这有一个栗子:假设我们以能装就装的原则,你可能会装的很满,那如果我最后一个物品重量为2,价值一个亿!!!,那你前面都装了,就装不下这一个亿的价值的东西了,因为我们前面所做的一切操作要考虑会面的情况,并不是找局部的最优解,而是整体考虑填表去寻找整体的最优解,因为局部的最优加起来不能代表全体的最优!
3、我们加速,列出动态函数:
V(i,j)=V(i-1,j) j<wi ;(装不下)
V(i,j)=max{ V(i-1,j),V(i-1,j-wi)+vi } j>=wi ;(能装下,前者不装,后者装)
4、ok我们开始列出我们另一个函数:关于物品取与不取的关系Xi:
Xi=0;表示第 i 个物品没有放入 V(i,j)= V(i-1,j)
Xi=1;表示第 i 个物品放入 V(i,j)> V(i-1,j) 或 V(i,j)= V(i-1,j-wi)+vi
**5、**列出动态规划表格
我们假设有5个物品,重量w{2,3,4,5}, 价值v{3,4,5,6},背包容量为8.
1.首先边界初始化:V(0,j)= V(i,0)=0
2.
如,i=1,j=1,w(1)=2,v(1)=3,有j<w(1),故V(1,1)=V(1-1,1)=0;
又如i=1,j=2,w(1)=2,v(1)=3,有j=w(1),故V(1,2)=max{ V(1-1,2),V(1-1,2-w(1))+v(1) }=max{0,0+3}=3;
如此下去,填到最后一个,i=4,j=8,w(4)=5,v(4)=6,有j>w(4),故V(4,8)=max{ V(4-1,8),V(4-1,8-w(4))+v(4) }=max{9,4+6}=10……
最终答案:V(4,8)=10;
代码实现
int KnapSack(int w[],int v[],int n,int C) { int i,j; for(i=0;i<=n;i++) { v[i][0]=0; } for(j=1;j<=c;j++) { v[0][j]=0; } for(i=1;i<=n;i++) { for(j=0;j<=c;j++) { if(j<w[i]) { v[i][j]=v[i-1][j]; } else{ v[i][j]=max(v[i-1][j],v[i-1][j-w[i]]+v[i]); } } for(j=c,i=n;i>0;i--) { if(v[i][j]>v[i-1][j]) { x[i]=1; j=j-w[i]; } else x[i]=0; } return v[n][c]; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。