原题目:
挑战任务
小绿是“绿盟”的工程师,这次准备参加团队组织的团建,本次团建他要负责携带团队所有人的零食,小绿目前只有一个容量为bagCapacity的背包,现在总共有num袋零食,每袋零食的体积不一定相同;小绿现在想知道在零食的总体积不超过自己背包容量的情况下,总共可以有多少种放零食的方法(体积为0也是一种放法)。
分析
如果有num袋零食,那么所有可能的摆放情况数为
刚开始的想法是直接用嵌套循环去搞定。但是嵌套的层数是不确定的:
如果摆放1袋零食,那么是一个单层循环;如果摆放2袋零食,那么想要判断所有可能的情况,需要一个双层嵌套循环;如果是3袋,那么需要三层…而我们需要讨论摆放0袋一直到摆放num袋的所有可能情况,这种算法实现起来非常困难(或者说根本不可能实现),所以只好另辟蹊径。
那么我们换一种思路,运用生活中的常识去解决问题:如果目前摆放n袋零食书包可以装得下,那么我们再从剩下的零食中拿一袋装进书包,可不可以装得下呢?如果可以,那我们再放进去一袋呢?如果不行,我们换一袋别的零食可不可以装得下呢?依此类推。
这就像我们日常生活中向包里面装东西的思路:挑一个放进包里,如果装不下就把这个拿出来,换一个放进去;如果装得下我们可能会继续向里面装其他东西。如此往复,直到装满为止。
这样的思路我们便可以用递归的方法去实现了。
源代码如下:
package app1;
import java.util.*;
public class Main {
public static int ways = 0;//作为全局变量,统计所有可行的方案数
public static void main(String[] args){//进行相关数据的输入、输出
int num, bagCapacity;
Scanner in = new Scanner(System.in);
num = in.nextInt();//零食袋数
bagCapacity = in.nextInt();//书包容量
long[] snacks = new long[num];//每袋零食的体积
for(int i = 0;i < num;i++){
snacks[i] = in.nextInt();//写入体积数据
}
getTheWay(num,bagCapacity,snacks,0,0);//调用递归函数统计方法数
System.out.println("所有可能的情况数:"+ways);//输出结果
}
public static void getTheWay(int num, int bagCapacity,long[] snacks,long weight,int tag){
if(weight <= bagCapacity){
ways++;//如果符合则方法数+1
for(int i=tag;i<num;i++){//看一看再装一袋零食可不可以
//变量tag是为了避免重复统计用的,具体可以参考穷举法
getTheWay(num,bagCapacity,snacks,weight+snacks[i],i+1);
}
}
}
}
测试结果:
①测试输入:20 130 1 5 2 1 9 3 23 12 3 4 7 8 10 11 12 13 14 15 16 12
输出结果:998906
②测试输入:21 1165911996 842104736 130059605 359419358 682646280 378385685 622124412 740110626 814007758 557557315 40153082 542984016 274340808 991565332 765434204 225621097 350652062 714078666 381520025 613885618 64141537 783016950
输出结果:703