背包问题描述
背包问题也是计算机中的经典问题。在最简单的形式中,需要将不同重量的数据项放到背包中,以使得背包最后达到指定的总重量。
比如:假设想要让背包精确地承重20磅,并且有 5 个可以放入的数据项,它们的重量分别是 11 磅,8 磅,7 磅,6 磅,5 磅。这个问题可能对于人类来说很简单,我们大概就可以计算出 8 磅+ 7 磅 + 5 磅 = 20 磅。但是如果让计算机来解决这个问题,就需要给计算机设定详细的指令了。
递归分析
1、递归的边界:
选择的数据项的总和符合目标重量——匹配
试验了所有的组合没有符合目标重量——不匹配
2、怎么递归:
从选择的第一个数据项开始,剩余的数据项的和必须符合背包的目标重量减去第一个数据项的重量——递归
如果没有合适的组合,放弃第一个数据项,并且从第二个数据项开始再重复一遍整个过程——递归
代码实现
package recursion;
public class RecursionTest9 {
public static void main(String[] args) {
int[] arr = new int[]{11,8,7,6,5};
Knapscak knapscak = new Knapscak(arr);
knapscak.doKnapsack(20,0);
}
}
//解决背包问题的类
class Knapscak{
private int[] data;//用来被选择的数组项组成的数组
private boolean[] selects;//这个数组和上面的data数组长度是一样的,true表示选择
//构造防范初始化上面的属性
public Knapscak(int[] data){
this.data = data;
selects = new boolean[data.length];
}
//具体的解决背包问题的方法
public void doKnapsack(int aim, int index){
//目标重量,索引序号
//边界条件
if (aim != 0 && index>=data.length){
//把所有的组合方案都试了,没找到匹配的组合
return;
}
if(aim == 0){
//找到了匹配的组合
for(int i=0;i<selects.length;i++){
if (selects[i]) {
System.out.print(data[i] + " ");
}
}
System.out.println();
return;
}
//循环
//将当前数据放进背包,进行尝试
selects[index] = true;
doKnapsack(aim-data[index],index+1);
//不将当前数据放进包里,进行尝试
selects[index] = false;
doKnapsack(aim,index+1);//从下一个数据项重来
}
}