动态规划 背包九讲的实现。
最近在学习动态规划,会了不少基础的之后就开始挑战比较困难的背包问题了,我这里自己写了每一讲的问题,解析,代码,注释。如果dp还没入门的孩纸就去看看我的另一篇文章http://www.cnblogs.com/luyi14/p/4344946.html
第一讲 0 1 背包
题目:
有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
解析:
最基础。
状态:0不装1装,是0 1 背包
转移方程:f[i][v] = max (f[i][v],f[i-1][v-c[i]]+w[i]);
一开始都看不懂这是什么玩意。变成一维的会好理解一点。看代码:
1 #include<stdio.h> 2 #define max(a,b) a>b?a:b 3 int main() 4 { 5 int v,n; 6 while(~scanf("%d%d",&v,&n)) 7 { 8 int c[101]={0},w[101]={0},f[1001]={0},i,j,k; 9 //这里定义初始值也是为了解决另一种问题就是恰好装满背包 10 //初始值就是除了f【0】=0.别的均-无穷就好 11 //已经不用吧背包装满。就如上代码 12 for(i = 1 ; i <= n ; i ++) 13 scanf("%d%d",&c[i],&w[i]); 14 for(i = 1 ; i <= n ; i++) 15 // 16 for(j = v;j >= c[i]; j--) 17 //优化 后面获得的数值不会影响到前面的这是肯定的、 18 f[j] = max(f[j],f[j-c[i]]+w[i]); 19 //等于转移方程 f[v] = max(f[i-1][v],f[i-1][v-c[i]); 20 printf("%d\n",f[v]); 21 } 22 return 0; 23 }
稍微先看看代码再来看解析:
刚才的方程式非常重要建议要彻底理解,将前i 件物品放入容量为v 的背包中,这个子问题,如果只考虑第i件物品 的策略 (0 1)那么问题就简化为前i -1 件物品放入的问题,(这里算是递归的思路吧不断缩短)前i - 1个物体放入剩下容量为 v - c【i】 的背包中 这时候的最大价值就是
f[i][v-c[i]] 加上第i件物品的价值w[i];
这个确实很难理解。看看一维的代码吧。
for i=1..N
for v=V..0
f[v]=max{f[v],f[v-c[i]]+w[i]};
这里就是用f【】来保存每一个物品放不放所导致的结果,
话就不多说了。还是自己把过程模拟一遍,才能真正去理解算法中精妙的dp吧。