幸运的袋子 --- 回溯法

Posted 满眼*星辰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了幸运的袋子 --- 回溯法相关的知识,希望对你有一定的参考价值。

一个袋子里面有n个球,每个球上面都有一个号码(拥有相同号码的球是无区别的)。如果一个袋子是幸运的当且仅当所有球的号码的和大于所有球的号码的积。
例如:如果袋子里面的球的号码是{1, 1, 2, 3},这个袋子就是幸运的,因为1 + 1 + 2 + 3 > 1 * 1 * 2 * 3
你可以适当从袋子里移除一些球(可以移除0个,但是别移除完),要使移除后的袋子是幸运的。现在让你编程计算一下你可以获得的多少种不同的幸运的袋子。
输入描述:
第一行输入一个正整数n(n ≤ 1000)
第二行为n个数正整数xi(xi ≤ 1000)
输出描述:
输出可以产生的幸运的袋子数
示例1
输入
3
1 1 1
输出
2

链接:https://www.nowcoder.com/questionTerminal/a5190a7c3ec045ce9273beebdfe029ee
来源:牛客网

import java.util.*;
 
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] num = new int[n];
        for (int i = 0; i < n; i++) {
            num[i] = scanner.nextInt();
        }
        //排序为了简化流程
        Arrays.sort(num);
        System.out.println(dfs(num,0,1,0));
    }

    public static int dfs(int[] num,int sum,int product,int index) {
        int count = 0;  //幸运袋子个数
        //从index位置开始遍历数组
        for (int i = index; i < num.length; i++) {
            sum += num[i];
            product *= num[i];
            if (sum > product) {    //如果和比积大,则个数加一,并向下递归
                count = count + 1 + dfs(num,sum,product,i+1);
            }else if(num[i] == 1) { //1特例,因为数字1能提高总和值但不会提高总积值,1的个数越多,和更有可能大于积,所以给它一次机会向下递归,但不+1
                count = count + dfs(num,sum,product,i+1);
            }else { //如果遇到了大于的情况,则不用向后遍历,因为数组有序,往后肯定越大,不可能再比sum小了
                break;
            }
            //回溯需要把sum和product回溯到上一递归的值。
            sum = sum-num[i];
            product = product/num[i];
            //注意:因为题目说了,拥有相同号码的球是无区别的,所以遇到相同的,往后遍历即可
            while (i+1 < num.length && num[i] == num[i+1]) {
                i++;
            }
        }
        return count;
    }
}

以上是关于幸运的袋子 --- 回溯法的主要内容,如果未能解决你的问题,请参考以下文章

幸运的袋子(深度优先遍历)

2017校招真题在线编程-幸运的袋子

每日一题 | day14(计算日期到天数转换 | 幸运的袋子)

0-1背包问题的回溯法代码

0-1背包问题的回溯法中,剪枝用的上界函数问题

用回溯法求01背包问题,怎样使用C++模板啊,迫切求指点!