递归-背包问题
背包问题有许多种形式,最简单的背包问题形式:现在有一堆石头,(比如重量为2,6,8,10),一个背包中可以装指定的重量(比如14)的石头,请问背包中可以放入的石头的组合。
代码中假设石头是个源数组,背包是目标数组。
算法中使用分治的想法将此问题递归为两个小范围的问题。
针对第n个石头,背包问题可以分解为两种组合的何:含第n个石头的背包的组合,与不含n个石头的背包的组合,
1.假设含第n个石头,背包问题变为,针对剩下的石头求得总重量减去第n个石头的重量的背包问题。
2.不含n个石头,背包问题变为针对剩下的石头求得总重量的背包问题。
class Bag {public static void main(String[] args) {int[] src = {2,4,5,7,8,6,10};select(14,src, 0, new int[src.length]);}/** * @param total 总数 * @param src 源数据数组 * @param offset 源数组的起始位置 * @param bag 背包,装选中的数据 */private static void select(int total, int [] src, int offset, int[] bag) {if(total == 0) {//背包要求增加的重量为0,则直接打印背包print(bag);return;}//从起始值开始寻找第一个小于要求增加重量的数值while(offset < src.length && total < src[offset]) offset++;if(offset >= src.length) return;//当没有源数据可以选择,则退出//将问题化简为在剩下的源数据中,两个找到重量的问题select(total,src,offset+1,bag.clone());//背包中不含有offset位置的select(total-src[offset],src,offset+1,put(bag,src[offset]));//背包中含有offset位置的}private static int[] put(int[] bag, int n) { //将数字放入背包中int pos = -1;while(bag[++pos] > 0);//找到背包中第一个数字为0的位置bag[pos] = n;return bag;}private static void print(int[] bag) {//打印背包中的数字System.out.print("bag: ");for(int n: bag) {if(n == 0) break;System.out.print(n + " ");}System.out.println();}}?