0-1背包问题复习
2015-05-05 18:01
141 查看
准备面试,通过做POJ上的题,复习算法知识,做POJ 3624复习了背包相关知识。
看背包九讲时有些实现细节不是很懂,于是就从最直接的实现开始实现0-1背包的动态规划算法,再逐渐写出优化后的解法。
状态转移方程便是:
f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
直接写出两层循环下的代码,N代表物品的数量,M表示最大背包能放下的最大容积,w[i]表示第i个物品的重量,d[i]表示第i个物品的价值。a[i][j]表示前i个物品放入容量为 j 的背包中获得的最大收益。
再写出空间优化后的代码,也就是内层循环倒写的写法,f[j]相当于之前的f[i][j]
对比两个写法,有几点需要注意:
第一个写法中的内层循环可以递增也可以递减,第二个则必须递减,递减写法保证第i次循环结束后f[v]中表示的就是我们定义的状态f[i][v],f[i][v]是由f[i-1][v]和f[i-1][v-c[i]]两个子问题递推而来,j的值递减保证在推f[i][v]时(也即在第i次主循环中推f[v]时)能够得到f[i-1][v]和f[i-1][v-c[i]]的值
第一个写法要加else,第二个不用加else。第二个写法中如果if不成立,f[j]不变,相当于第一个写法中将a[i][j] = a[i-1][j]。
第一个中的i值必须从1开始,第二个的i值则不要求。
版权声明:本文为博主原创文章,未经博主允许不得转载。
看背包九讲时有些实现细节不是很懂,于是就从最直接的实现开始实现0-1背包的动态规划算法,再逐渐写出优化后的解法。
状态转移方程便是:
f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
直接写出两层循环下的代码,N代表物品的数量,M表示最大背包能放下的最大容积,w[i]表示第i个物品的重量,d[i]表示第i个物品的价值。a[i][j]表示前i个物品放入容量为 j 的背包中获得的最大收益。
for (int i = 1; i <= N ; i ++) { for (int j = 0; j <= M ; j ++) { if (j - w [i ] >= 0) { a[i][j] = Math.max(a[i-1][j],a[i-1][j-w [i]] + d[i]); } else{ a[i][j] = a[i-1][j]; } } }
再写出空间优化后的代码,也就是内层循环倒写的写法,f[j]相当于之前的f[i][j]
for (int i = 1; i <= N; i++) { for (int j = M; j >= 0; j--) { if (j - w[i] >= 0) { f[j] = Math.max(f[j], f[j - w[i]] + d[i]); } }
对比两个写法,有几点需要注意:
第一个写法中的内层循环可以递增也可以递减,第二个则必须递减,递减写法保证第i次循环结束后f[v]中表示的就是我们定义的状态f[i][v],f[i][v]是由f[i-1][v]和f[i-1][v-c[i]]两个子问题递推而来,j的值递减保证在推f[i][v]时(也即在第i次主循环中推f[v]时)能够得到f[i-1][v]和f[i-1][v-c[i]]的值
第一个写法要加else,第二个不用加else。第二个写法中如果if不成立,f[j]不变,相当于第一个写法中将a[i][j] = a[i-1][j]。
第一个中的i值必须从1开始,第二个的i值则不要求。
package PackProblem; import java.util.Scanner; /** * O-1背包,数组长度有误,要开到14000才AC. * 5412K,2532MS * @author DaiSong * @Date 2014年3月2日 */ public class Poj_3624 { static int f[] = new int[15000]; public static int ZeroOnePack(int d[], int w[], int n, int m) { for(int i = 0; i < n; i++) { for (int j = m; j >= 0; j--) { if (j - w[i] >= 0) { f[j] = Math.max(f[j], f[j - w[i]] + d[i]); } } for (int j = 0; j <= m; j++) { System.out.print(f[j] + " "); } System.out.println(); } return f[m]; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n, m; int d[] = new int[15000]; int w[] = new int[15000]; n = sc.nextInt(); m = sc.nextInt(); for (int i = 0; i < n; i++) { w[i] = sc.nextInt(); d[i] = sc.nextInt(); } System.out.println(ZeroOnePack(d, w, n, m)); } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
相关文章推荐
- NOIP专题复习(一) 基础的背包问题
- 背包问题复习2
- 【算法复习三】算法设计技巧与优化----各种背包问题总结
- 【算法复习三】算法设计技巧与优化----各种背包问题总结
- 背包问题复习
- (复习)poj 1742 coins 多重背包可达性问题
- DP复习——背包问题的变化
- codevs 1155今明的预算方案(复习有依赖性的背包问题)
- 算法复习——背包DP问题
- 【算法复习二】0-1背包问题总结
- 0-1背包问题复习
- DP复习——有依赖的背包问题
- 【算法复习二】0-1背包问题总结
- 多重背包问题的二进制分解思想
- 背包问题
- 从goto问题开始复习下java循环基础
- php回溯法解决0-1背包问题
- 全是套路——背包问题(还有待检验)
- poj 2385 背包问题变形
- 背包问题