递归-背包问题

背包问题有许多种形式,最简单的背包问题形式:现在有一堆石头,(比如重量为2,6,8,10),一个背包中可以装指定的重量(比如14)的石头,请问背包中可以放入的石头的组合。

代码中假设石头是个源数组,背包是目标数组。

算法中使用分治的想法将此问题递归为两个小范围的问题。

针对第n个石头,背包问题可以分解为两种组合的何:含第n个石头的背包的组合,与不含n个石头的背包的组合,

1.假设含第n个石头,背包问题变为,针对剩下的石头求得总重量减去第n个石头的重量的背包问题。

2.不含n个石头,背包问题变为针对剩下的石头求得总重量的背包问题。

Java代码   收藏代码
  1. class Bag {  
  2.     public static void main(String[] args) {  
  3.         int[] src = {2,4,5,7,8,6,10};  
  4.         select(14,src, 0new int[src.length]);  
  5.     }  
  6.       
  7.     /** 
  8.      * @param total 总数 
  9.      * @param src 源数据数组 
  10.      * @param offset 源数组的起始位置 
  11.      * @param bag 背包,装选中的数据 
  12.      */  
  13.     private static void select(int total, int [] src, int offset, int[] bag) {  
  14.         if(total == 0) {    //背包要求增加的重量为0,则直接打印背包  
  15.             print(bag);  
  16.             return;  
  17.         }  
  18.         //从起始值开始寻找第一个小于要求增加重量的数值  
  19.         while(offset < src.length && total < src[offset]) offset++;  
  20.         if(offset >= src.length) return//当没有源数据可以选择,则退出  
  21.         //将问题化简为在剩下的源数据中,两个找到重量的问题  
  22.         select(total,src,offset+1,bag.clone()); //背包中不含有offset位置的  
  23.         select(total-src[offset],src,offset+1,put(bag,src[offset]));//背包中含有offset位置的  
  24.     }  
  25.       
  26.     private static int[] put(int[] bag, int n) { //将数字放入背包中  
  27.         int pos = -1;  
  28.         while(bag[++pos] > 0);   //找到背包中第一个数字为0的位置  
  29.         bag[pos] = n;  
  30.         return bag;  
  31.     }  
  32.   
  33.     private static void print(int[] bag) {  //打印背包中的数字  
  34.         System.out.print("bag: ");  
  35.         for(int n: bag) {  
  36.             if(n == 0break;  
  37.             System.out.print(n + " ");  
  38.         }  
  39.         System.out.println();  
  40.     }  
  41. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值