背包问题(求和,神奇的口袋)java

1.求和

输入两个整数 n 和 m,从数列1,2,3.......n 中随意取几个数,使其和等于 m ,要求将其中所有的可能组合列出来

题目解析:基于递归实现 dfs(深度优先搜索) 即可. 这是一个比较典型的背包问题

思路:假设问题的解为F(n, m),可分解为两个子问题 F(n-1, m-n)和F(n-1, m)。对这两个问题递归求解,求解过程 中,如果找到了符合条件的数字组合,则打印出来 例如 1, 2, 3, 4, 5, 求有多少中组合和为 5 对于 1 这个元素 来说, 可能会放到结果中, 可能不放到结果中 如果放到结果中, 就相当于求 2...5 中取若干个数字和为 4. (即为 F(n-1, m-n)) 如果不放到结果中, 就相当于求 2...5 中取若干个数字和为 5. (即为F(n-1, m))


import java.util.ArrayList;
import java.util.Scanner;

public class Main { 
// res 用于保存最终结果
    static ArrayList> res = new ArrayList>();
    static ArrayList list = new ArrayList<>();

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n, m;
        while (sc.hasNext()) {
            n = sc.nextInt();
            m = sc.nextInt();       
            // 核心逻辑在此. 注意理解 m, n 的含义.          
            // 题目要求是求 1...n 中取若干个数, 和为 m
            dfs(1, m, n);        
            // 打印结果集合
            for (ArrayList l : res) {
                int i = 0;
                for (; i < l.size() - 1; i++) {
                    System.out.print(l.get(i) + " ");
                }
                System.out.println(l.get(i));
            }
        }
    }

    public static void dfs(int index, int count, int n) {
        if (count == 0) {
            res.add(new ArrayList<>(list));
        } else {
            for (int i = index; i <= count && i <= n; i++) {
                list.add(i);            
                // 此处进行了递归, 对问题进行拆解.              
                // 求 1...n 中取若干个数字和为 m, 能把问题拆解为             
                // 求 2...n 中取若干给数字, 和为 m - 1
                dfs(i + 1, count - i, n);
                list.remove(list.size() - 1);
            }
        }
    }
}

2.神奇的口袋

有一个神奇的口袋,总的容积是40,用这个口袋可以变出一些物品,这些物品的总体积必须是40。John现在有n个想要得到的物品,每个物品的体积分别是a1,a2……an。John可以从这些物品中选择一些,如果选出的物体的总体积是40,那么利用这个神奇的口袋,John就可以得到这些物品。现在的问题是,John有多少种不同的选择物品的方式。

这是一个排列组合的问题。

题目解析: 采用递归思想: ①物品n个,物品体积逐一放入weight[]中 ②递归函数count(int s,int n) : 其 中s为剩余物品重量,n为剩余可选的物品个数
则分以下两步递归求解:
a.从后往前装,装上weight[n]后,若剩余物品仍然有解 则count(s-weight[n],n-1);
b.若装了weight[n]后,无解,则删除该包,尝试第n-1个 count(s,n-1);

import java.util.*;

public class test {
    static int[] weight;
    static int N;
    static int count = 0;

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);

        while (input.hasNext()) {
            N = input.nextInt();
            weight = new int[N + 1];

            for (int i = 1; i <= N; i++) {
                weight[i] = input.nextInt();
            }
            count(40, N);
            System.out.println(count);
        }
    }

    public static void count(int s, int n) {     //如果正好装满
        if (s == 0) {
            ++count;
            return;
        }
        //是s<0或n<1则不能完成
        if (s < 0 || (s > 0 && n < 1)) return;
        count(s - weight[n], n - 1);
        count(s, n - 1);
    }
}

 

 

你可能感兴趣的:(编程)