牛牛的背包问题

Problem: 牛牛的背包问题

文章目录

  • 思路
  • 解题方法
  • 复杂度
  • Code

思路

牛牛准备参加学校组织的春游, 出发前牛牛准备往背包里装入一些零食, 牛牛的背包容量为w。
牛牛家里一共有n袋零食, 第i袋零食体积为v[i]。
牛牛想知道在总体积不超过背包容量的情况下,他一共有多少种零食放法(总体积为0也算一种放法)。
数据范围:第一行为两个正整数n和w(1 <= n <= 30, 1 <= w <= 2 * 10^9),表示零食的数量和背包的容量。
很显然这个题目要使用双向广搜,数据量过大不宜使用动态规划

解题方法

划分为左右两边进行展开(暴搜),最后使用双指针进行合并

复杂度

时间复杂度:

在compute()函数中,调用了两次f()函数,每次都会递归调用自身两次,所以总共会有2^n次递归调用。
在f()函数中,每次递归调用都会有两个分支,所以总共会有2^n个递归结束的情况。
在每个递归结束的情况下,会将当前的和s加入到ans数组中,而ans数组的长度最大为2^n。
在最后的循环中,会对lsum和rsum数组进行排序,排序的时间复杂度为 O ( 2 n ∗ l o g ( 2 n ) ) O(2^n * log(2^n)) O(2nlog(2n))

空间复杂度:

在compute()函数中,定义了lsum和rsum两个数组,数组的长度最大为2^n。
在f()函数中,每次递归调用都会有一个新的ans数组,数组的长度最大为2^n。
在nextInt()和nextLong()函数中,定义了一个StreamTokenizer对象,占用常数级的空间。
综上所述空间复杂度为 O ( 2 n ) O(2^n) O(2n)

Code

import java.util.*;
import java.io.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
    static StreamTokenizer sr = new StreamTokenizer(in);
    static int MAXN = 40;
    static int MAXM = 1 << 20;
    static long[] arr = new long[MAXN];
    static long[] lsum = new long[MAXM];
    static long[] rsum = new long[MAXM];
    static int n;
    static long w;
    public static void main(String[] args) throws IOException {
        n = nextInt();
        w = nextLong();
        for (int i = 0; i < n; i++) {
            arr[i] = nextLong();
        }
        out.println(compute());
        out.flush();
    }
    public static long compute() {
        int lszie = f(0, n >> 1, 0, w, lsum, 0);
        int rsize = f(n >> 1, n, 0, w, rsum, 0);
        Arrays.sort(lsum, 0, lszie);
        Arrays.sort(rsum, 0, rsize);
        long ans = 0;
        for(int i = lszie - 1, j = 0; i >= 0; i--) {
            while(j < rsize && lsum[i] + rsum[j] <= w) {
                j++;
            }
            ans += j;
        }
        return ans;
    }
    public static int f(int i, int e, long s, long w, long[] ans, int j) {
        if(s > w) {
            return j;
        }
        if(i == e) {
            ans[j++] = s;
        } else {
            j = f(i + 1, e, s, w, ans, j);
            j = f(i + 1, e, s + arr[i], w, ans, j);
        }
        return j;
    }
    static int nextInt() throws IOException {
        sr.nextToken();
        return (int)sr.nval;
    }
    static long nextLong() throws IOException {
        sr.nextToken();
        return (long)sr.nval;
    }
}

你可能感兴趣的:(刷题,算法,java,数据结构,dfs)