算法学习笔记(二)——01背包问题之回溯解法
来源:互联网 发布:keilc51下载西西软件 编辑:程序博客网 时间:2024/06/03 15:59
我们知道,回溯法的效率并不是很高的!因为回溯法,就其本质而言,还是属于穷举!只不过它就提供了一个穷举的思路:回溯!的确也是这样,上面代码中的例子中的物品只由5个,换句话说,所构成的二叉树也只有5层!但当物品有10个,20个,甚至100个话,构成的二叉树是多么的庞大!(笔者觉得不可想象深度为100的二叉树)!故在上述代码的基础上,很有必要去做一个算法的优化!在网上看了别人的博客之后,大致知道了一个思路:即在不断的遍历左子树(即不断的将物品装入)的过程中,如果出现了不能再装入下一物品的情况时,这时就需要去遍历右子树!但是如果,如果在剩余容量情况下,将剩余容量的背包装满(如果大于0且小于物品的重量的话,按照单位重量的价值乘以剩余容量来算)的情况下 得到的总价值比当前最优解还要的小的话,那么该右子树是完全没有必要去遍历,而需要直接剪除的!这样就达到了优化的目的!废话不多说,直接上代码:public class Demo1 {private static int c = 10; //背包容量private static int[] w= {0,2,2,6,5,5};//每个物体的重量:5个物体private static int[] v = {0,6,3,5,4,6};//每个物体的价值private static int[] x= new int[6];//存放每个物体的选中情况private static int bestcp = 0;//当前的最优解private static int[] bestcpArr = new int[6];private static int count = 0;private static int n = 5;//物体的数目public static void main(String[] args) {backtrack(1, 0 ,0);for(int i =0 ; i < bestcpArr.length ;i++){System.out.print(bestcpArr[i]);}System.out.println("");System.out.println(bestcp);System.out.println("该树有" + count +"种遍历方式");}/** * * @param i:查找到了第i个物品(i从1开始索引) * @param cv:当前包中价值 * @param cw:当前包中重量 */private static void backtrack(int i , int cw , int cv) {count++;if (i > n) {if (cv > bestcp) {bestcp = cv;for(int j = 0 ; j < 6 ;j++){bestcpArr[j]= x[j];}}}else{//开始遍历,如果k=0,则表示不装下此物品,k=1,则表示装下此物品for(int k = 0 ; k <= 1; k++){x[i] = k;if (cw + w[i] <= c) {cv += v[i] * k;cw +=w[i] * k;backtrack(i + 1, cw, cv);cv -= v[i] * k;cw -=w[i] * k;}}}}}
/**
*本算法的上界函数是这样定义的!首先利用冒泡法排序,按照单位价值右高到低开始顺序排列!
*这样的话,就能保证,先装进去的是性价比(自己发明的,勿喷)最优的!而在上界函数中,也是如此,求的是剩余
* 容量在右子树所能容纳的最高价值(背包容量允许情况下),一旦小于当前最优解,那么就
* 没有继续遍历该右子树的必要
*
*/
public class Demo2 {private static int n;// 物品数量private static double c;// 背包容量private static double[] v = new double[100];// 各个物品的价值private static double[] w = new double[100];// 各个物品的重量private static double cw = 0.0;// 当前背包重量private static double cp = 0.0;// 当前背包中物品价值private static double bestp = 0.0;// 当前最优价值private static double[] perp = new double[100];// 单位物品价值排序后private static int order[] = new int[100];// 物品编号private static int[] put = new int[100];// 设置是否装入// 按单位价值排序private static void knapsack() {int i, j;int temporder = 0;double temp = 0.0;for (i = 1; i <= n; i++)perp[i] = v[i] / w[i];for (i = 1; i <= n - 1; i++) {for (j = i + 1; j <= n; j++)if (perp[i] < perp[j])// 冒泡排序perp[],order[],sortv[],sortw[]{temp = perp[i];perp[i] = perp[i];perp[j] = temp;temporder = order[i];order[i] = order[j];order[j] = temporder;temp = v[i];v[i] = v[j];v[j] = temp;temp = w[i];w[i] = w[j];w[j] = temp;}}}// 回溯函数private static void backtrack(int i) {if (i > n) {bestp = cp;return;}//将物品装进背包:此种情况的话if (cw + w[i] <= c) {cw += w[i];cp += v[i];put[i] = 1;backtrack(i + 1);cw -= w[i];cp -= v[i];}if (bound(i + 1) > bestp)// 符合条件搜索右子数backtrack(i + 1);}// 计算上界函数
//算法剩余容量的情况下最多能装的价值private static double bound(int i) {double leftw = c - cw;double b = cp;while (i <= n && w[i] <= leftw) {leftw -= w[i];b += v[i];i++;}if (i <= n)b += v[i] / w[i] * leftw;return b;}public static void main(String[] args) {// private static int[] w= {0,2,2,6,5,5}; //每个物体的重量:5个物体// private static int[] v = {0,6,3,5,4,6}; //每个物体的价值v[0] = 0;v[1] = 6;v[2] = 3;v[3] = 5;v[4] = 4;v[5] = 6;w[0] = 0;w[1] = 2;w[2] = 2;w[3] = 6;w[4] = 5;w[5] = 5;n = 5;c = 10;knapsack();backtrack(1);System.out.println(bestp);for (int i = 1; i <= n; i++) {System.out.print(put[i] + " ");}System.out.println("");}}
- 算法学习笔记(二)——01背包问题之回溯解法
- 【算法笔记】回溯法——01背包问题
- 算法学习笔记(一)——全排列问题之回溯法
- 01背包问题(回溯算法实现)
- 01背包问题(回溯算法实现)
- 回溯算法---01背包问题
- N皇后问题(回溯算法解法)
- 回溯法-01背包问题之二:顺序执行模式
- 0029算法笔记——【回溯法】n后问题和0-1背包问题
- 0029算法笔记——【回溯法】n后问题和0-1背包问题
- 回溯算法之0-1背包问题
- 回溯算法--背包问题
- 回溯法——01背包问题
- 0-1背包问题及其动态规划求解之二——王晓东的书本解法
- NOJ(1004)-回溯算法-01背包问题
- 0-1背包问题:(回溯算法)
- 0-1背包问题:(回溯算法)
- 0-1背包问题(回溯算法)
- 算法学习笔记(一)——全排列问题之回溯法
- JAVA容器类总结
- Android中去掉标题栏或全屏的方法
- GIMP简介
- 环境搭建笔记(一)——Maven配置Struts2+Spring4+Mybatis3运行环境
- 算法学习笔记(二)——01背包问题之回溯解法
- 关系型数据库工作原理-事务管理(一)(翻译自Coding-Geek文章)
- 算法学习笔记(三)——全排列生成算法:next_permutation
- 如何通过cmd命令进行硬盘分区(附加gpt转换成mbr)
- DuiLib(3)——DuiLib与MFC嵌套攻略
- 电商平台学习笔记(七)——模板方法结合Spring在DAO层的应用
- 2016.4.3 JS学习
- next_permutation函数
- 最常用的链接