zoukankan      html  css  js  c++  java
  • 背包问题

    • 0-1背包问题  :每个物品只有1件
    • 完全背包问题:每个物品有无数件
    • 多重背包问题:每个物品有不超过多少件的限制
    • 混合背包问题:物品有的是1件,有的无数件,有的不超过多少件

    1、0-1背包问题

    题目描述:

      有N件物品和一个容量是bagV的背包,每件物品只能使用一次。第 i件物品的体积是 v[i],价值是 w[i]
      求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。

    思路:

    对于每一个物品,有两种结果:能装下或者不能装下。

    • 如果不能装下,这时的最大价值和前i-1个物品的最大价值是一样的;
    • 如果能装下,装了不一定大于当前相同体积的最优价值,所以要对装该商品与不装该商品得到的最大价值进行比较,取最大的那个。

    f[i][j]表示:背包容量为j时,前i个物品所能达到的最大价值。0<=j<=V
    第i个商品体积为vi,价值为wi,则状态转移方程:

    • j<vi, f[i][j] = f[i-1][j]     //背包装不下此物品,最大价值不变,还是为前i-1的最大价值
    • j>=vi,f[i][j] = max{f[i-1][j],f[i-1][j-vi]+wi}    // 背包装得下,最大价值取装与不装该物品时同样达到该体积的最大价值
        /**
         * 利用二维数组
         * @param N  N个物品
         * @param bagV  背包体积为bagV
         * @param v  物品体积(v[i]表示第i个物品体积,v[0]=0)
         * @param w  物品价值(w[i]表示第i个物品价值,w[0]=0)
         */
        public static int bag0_1(int N, int bagV, int[] v, int[] w) {
            
            //f[i][j]表示背包容量为j时前i个商品的最大价值
            int[][] f = new int[N+1][bagV+1];
            for(int i = 1; i <= N; i++) {
                for(int j = 0; j <= bagV; j++) {
                    if(j < v[i])
                        f[i][j] = f[i-1][j];
                    else
                        f[i][j] = Math.max(f[i-1][j], f[i-1][j-v[i]]+w[i]);
                }
            }
            return f[N][bagV];
        }
    View Code

    用一维数组的话,设f[j]表示背包容量为j时的最大价值,状态转移方程:f[j] = max[f[j],f[j-vi]+wi}

        /**
         * 利用一维数组实现
         * @param N  N个物品
         * @param bagV  背包体积为bagV
         * @param v  物品体积(v[i]表示第i个物品体积,v[0]=0)
         * @param w  物品价值(w[i]表示第i个物品价值,w[0]=0)
         */
        public static int bag0_1(int N, int bagV, int[] v, int[] w) {
            //f[j]表示背包体积为j时最大价值
            int[] f = new int[bagV + 1];
            for(int i = 1; i <= N; i++) {
                for(int j = bagV; j >= v[i]; j--)
                    f[j] = Math.max(f[j], f[j-v[i]]+w[i]);
            }
            return f[bagV];
        }

    注:如果要求恰好装满背包:

    求法相同,不过初始化是除了f[1]初始化为0(背包容量为1时的最大价值为0),其他都初始化为负无穷

        /**
         * 在恰好装满背包的情况下最多获取多少价值?
         * 初始化时,除了f[i][1]为0外(第一列),其他全为负无穷
         */
        public static int fullBag0_1(int N, int bagV, int[] v, int[] w) {
            int[] f = new int[bagV+1];
            //除了f[i][1]其他都为负无穷
            for(int j = 2; j < bagV; j++) {
                f[j] = Integer.MIN_VALUE;//其他全为负无穷
            }
    
            for(int i = 1; i <= N; i++) {
                for (int j = bagV; j >= v[i]; j--) 
                    f[j] = Math.max(f[j], f[j - v[i]] + w[i]);
            }
            int res =  f[bagV];
            if(res < 0)
                res = -1;
            return res;
        }

    2、完全背包问题

     题目描述:

      有 N 种物品和一个容量是 bag的背包,每种物品都有无限件可用第 i 种物品的体积是 vi,价值是 wi

      求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。

    思路:

    设f[i][j]表示背包容量为j时,前i个物品所能达到的最大价值。0<=j<=bagV
    第i个商品体积为vi,价值为wi,则状态转移方程:

    • j<vi,f[i][j] = f[i-1][j]     //背包装不下此物品,最大价值不变,还是为前i-1的最大价值
    • j>=vi,f[i][j] = max{f[i-1][j],f[i-1][j-k*vi]+k*wi}   //背包装得下,最大价值取装与不装该物品时同样达到该体积的最大价值,与0-1不同的是,可以装k个。
        /**
         * 利用二维数组实现
         * @param N  N个物品
         * @param bagV  背包体积为bagV
         * @param v  物品体积(v[i]表示第i个物品体积,v[0]=0)
         * @param w  物品价值(w[i]表示第i个物品价值,w[0]=0)
         */
        public static int competeBag(int N, int bagV, int[] v, int[] w) {    
            //f[i][j]表示背包容量为j时前i个商品的最大价值
            int[][] f = new int[N+1][bagV+1];
            for(int i = 1; i <= N; i++) {
                for(int j = 0; j <= bagV; j++) {
                    if(j < v[i]){
                        f[i][j] = f[i-1][j];
                    }else{
                        for(int k = 1; k*v[i] <= j; k++)
                            f[i][j] = Math.max(f[i-1][j], f[i-1][j-k*v[i]]+k*w[i]);
                    }
                }
            }
            return f[N][bagV];
        }
    View Code

      利用一维数组的话,设f[j]表示背包容量为j时的最大价值,状态转移方程:f[j] = max[f[j],f[j-k*vi]+k*wi}

    /**
         * 利用一维数组实现
         * @param N  N个物品
         * @param bagV  背包体积为bagV
         * @param v  物品体积(v[i]表示第i个物品体积,v[0]=0)
         * @param w  物品价值(w[i]表示第i个物品价值,w[0]=0)
         */
        public static int competeBag(int N, int bagV, int[] v, int[] w) {    
            //f[j]表示背包容量为j时商品的最大价值
            int[] f = new int[bagV+1];
            for(int i = 1; i <= N; i++) {
                for(int j = 0; j <= bagV; j++) {
                    for(int k = 1; k * v[i] <= j; k++) {
                        f[j] = Math.max(f[j], f[j-k*v[i]]+k*w[i]);
                    }
                }
            }
            return f[bagV];
        }
    View Code

    优化代码:与0-1背包不同的是第二层循环j从小到大顺序遍历(0-1背包是从大到小逆序遍历)

        /**
         * 利用一维数组实现
         * @param N  N个物品
         * @param bagV  背包体积为bagV
         * @param v  物品体积(v[i]表示第i个物品体积,v[0]=0)
         * @param w  物品价值(w[i]表示第i个物品价值,w[0]=0)
         */
        public static int competeBag(int N, int bagV, int[] v, int[] w) {    
            //f[j]表示背包容量为j时商品的最大价值
            int[] f = new int[bagV+1];
            for(int i = 1; i <= N; i++) {
                for(int j = v[i]; j <= bagV; j++)
                    f[j] = Math.max(f[j], f[j-v[i]]+w[i]);
            }
            return f[bagV];
        }

    3、多重背包问题

    题目描述:

      有 种物品和一个容量是 bagV 的背包。第 i 种物品最多有 s,每件体积是 vi,价值是 wi。

      求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。输出最大价值。

    思路:

      和完全背包类似,不同的是第二层循环j时多了一个对物品个数的限制。

        /**
         * 利用一维数组实现
         * @param N  N个物品
         * @param bagV  背包体积为bagV
         * @param v  物品体积(v[i]表示第i个物品体积,v[0]=0)
         * @param w  物品价值(w[i]表示第i个物品价值,w[0]=0)
         * @param s  s[i]表示第i个物品最多有多少个 ,s[0]=0
         */
        public static int multipleBag(int N, int bagV, int[] v, int[] w, int[] s) {    
            //f[j]表示背包容量为j时商品的最大价值
            int[] f = new int[bagV+1];
            for(int i = 1; i <= N; i++) {
                for(int j = 0; j <= bagV; j++) {
                    for(int k = 1; k <= s[i] && k * v[i] <= j; k++) {
                        f[j] = Math.max(f[j], f[j-k*v[i]]+k*w[i]);
                    }
                }
            }
            return f[bagV];
        }

    利用二进制优化,转化为0-1背包问题:

      一个数a,我们可以按照二进制来分解为 a=1+2+4+8……+2^n+剩下的数,我们把a拆成这么多项,可以证明,这么多项可以组合出1~a的每一个数。

      不管最优策略选择几件第i种物品,总可以表示成若干件物品的和。利用二进制拆分将a拆成若干数字的和,假设拆成M个数字,则这样把原问题转化为物品数量为M的0-1背包问题

    //先定义一个类来存放新商品
    class Goods {
        int v; //体积
        int w; //价值
        public Goods(int v, int w) {
            this.v = v;
            this.w = w;
        }
    }
    -----------------------------------------------
    
        /**
         * 二进制优化,转为0-1背包问题来实现
         * @param N  N个物品
         * @param bagV  背包体积为bagV
         * @param v  物品体积(v[i]表示第i个物品体积,v[0]=0)
         * @param w  物品价值(w[i]表示第i个物品价值,w[0]=0)
         * @param s  s[i]表示第i个物品最多有多少个 ,s[0]=0
         */
        public static int multipleBag(int N, int bagV, int[] v, int[] w, int[] s) {    
            //存放新商品的体积、价值
            ArrayList<Goods> list = new ArrayList<Goods>();
            //s[i]拆为一些数的和,重新存放商品,二进制转换为0-1背包问题
            for(int i = 1; i <= N; i++) {
                int ss = s[i];
                for(int k = 1; k <= ss; k *= 2) {
                    ss -= k;
                    list.add(new Goods(k*v[i], k*w[i]));
                }
                //剩下的数
                if(ss > 0)
                    list.add(new Goods(ss*v[i], ss*w[i]));
            }
            
            //按照0-1背包问题求解
            int[] f = new int[bagV+1];
            for(Goods good : list) {
                for(int j = bagV; j >= good.v; j--) {
                    f[j] = Math.max(f[j], f[j-good.v]+good.w);
                }
            }
            return f[bagV];
            
        }

    4、混合背包问题

    有 N种物品和一个容量是 bagV的背包。物品一共有三类

    • 第一类物品只能用1次(01背包);
    • 第二类物品可以用无限次(完全背包);
    • 第三类物品最多只能用 si 次(多重背包);

    每种体积是 vi,价值是 wi。
    求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。输出最大价值。

    这里我们给出输入输出格式:

    输入格式:
      第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。
      接下来有 N行,每行三个整数 vi,wi,si,用空格隔开,分别表示第 i种物品的体积、价值和数量。
        si=−1 表示第 i种物品只能用1次;
        si=0 表示第 i种物品可以用无限次;
        si>0 表示第 i种物品可以使用 si 次;
    输出格式:
      输出一个整数,表示最大价值。

    输入样例:
    4 5
    1 2 -1
    2 4 1
    3 4 0
    4 5 2
    输出样例:8

    思路:

      将多重背包转换为0-1背包进行处理,所以最后只需要处理两种背包:0-1背包与完全背包。

    //定义一个Goods类
    class Goods {
        int v; //体积
        int w; //价值
        int s; //物品类型:-1、0、>0
        public Goods(int v, int w, int s) {
            this.v = v;
            this.w = w;
            this.s = s;
        }    
    }
    
    public class Main {
    
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int N = sc.nextInt(); //N个物品
            int bagV = sc.nextInt(); //背包容积为bagV
            //存储物品的体积和价值
            int[] v = new int[N+1]; //体积
            int[] w = new int[N+1]; //价值
            int[] s = new int[N+1]; //物品类型:-1--只有1件、0--有无数件、>0--有这些件
            for(int i = 1; i <= N; i++) {
                v[i] = sc.nextInt();
                w[i] = sc.nextInt();
                s[i] = sc.nextInt();
            }
            System.out.println(mixtureBag(N, bagV, v, w, s));
        }
        
        /*
         * s[i]=-1: 0-1背包
         * s[i]=0 :完全背包
         * s[i]>0 :多重背包
         * 多重背包可以转换为0-1背包进行处理
         */
        public static int mixtureBag(int N, int bagV, int[] v, int[] w, int[] s) {
            //存放商品的 体积、价值、类型
            ArrayList<Goods> list = new ArrayList<Goods2>();
            
            for(int i = 1; i <= N; i++){
                if(s[i] == -1 || s[i] == 0)
                    list.add(new Goods(v[i], w[i], s[i]));
                else {
                    //多重背包二进制优化转为0-1背包问题
                    int ss = s[i];
                    for(int k = 1; k <= s[i]; k *= 2) {
                        ss -= k;
                        list.add(new Goods(k*v[i], k*w[i], -1));
                    }
                    if(ss > 0)
                        list.add(new Goods(ss*v[i], ss*w[i], -1));
                }
            }
            
            int[] f = new int[bagV+1];
            for(Goods good : list) {
                //0-1背包
                if(good.s == -1){
                    for(int j = bagV; j >= good.v; j--)
                        f[j] = Math.max(f[j], f[j-good.v]+good.w);
                }
                //完全背包
                else{
                    for(int j = good.v; j <= bagV; j++)
                        f[j] = Math.max(f[j], f[j-good.v]+good.w);
                }
            }
            return f[bagV];
        }
        
    }

     5、二维费用的背包问题

    题目描述:

      有 件物品和一个容量是 V 的背包,背包能承受的最大重量是 M。每件物品只能用一次。体积是 vi,重量是 mi,价值是 wi

    求解将哪些物品装入背包,可使物品总体积不超过背包容量,总重量不超过背包可承受的最大重量,且价值总和最大。输出最大价值。

    输入格式:

      第一行两个整数,NV,M,用空格隔开,分别表示物品件数、背包容积和背包可承受的最大重量。

      接下来有 N 行,每行三个整数 vimiwi,用空格隔开,分别表示第 i 件物品的体积、重量和价值。

    输出格式

      输出一个整数,表示最大价值。

    输入样例

    4 5 6
    1 2 3
    2 4 4
    3 4 5
    4 5 6
    

    输出样例:8

        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
    
            int N = sc.nextInt();  //物品数
            int bagV = sc.nextInt(); //背包体积
            int bagM = sc.nextInt(); //背包重量
            int[] v = new int[N+1];
            int[] m = new int[N+1];
            int[] w = new int[N+1];
            for(int i = 1; i <= N; i++) {
                v[i] = sc.nextInt();
                m[i] = sc.nextInt();
                w[i] = sc.nextInt();
            }
            System.out.println(bag2D(N, bagV, bagM, v, m, w));
        }
    public static int bag2D(int N, int bagV, int bagM, int[] v, int[] m, int[] w) { //f[i][j]表示背包容量为i、重量为j时的最大价值 int[][] f = new int[bagV+1][bagM+1]; for(int k = 1; k <= N; k++) //第k个物品 //都要倒序 for(int i = bagV; i >= v[k]; i--) for(int j = bagM; j >= m[k]; j--) f[i][j] = Math.max(f[i][j], f[i-v[k]][j-m[k]]+w[k]); return f[bagV][bagM]; }

    6、分组背包问题

    题目描述:

      有 N 组物品和一个容量是 V 的背包。每组物品有若干个,同一组内的物品最多只能选一个。每件物品的体积是 vij,价值是 wij,其中 i是组号,j 是组内编号。

      求解将哪些物品装入背包,可使物品总体积不超过背包容量,且总价值最大。输出最大价值。

    输入格式

      第一行有两个整数 NVN,V,用空格隔开,分别表示物品组数和背包容量。

      接下来有 NN 组数据:

      • 每组数据第一行有一个整数 SiSi,表示第 ii 个物品组的物品数量;
      • 每组数据接下来有 SiSi 行,每行有两个整数 vij,wijvij,wij,用空格隔开,分别表示第 ii 个物品组的第 jj 个物品的体积和价值;

    输出格式

      输出一个整数,表示最大价值。

    输入样例

    3 5
    2
    1 2
    2 4
    1
    3 4
    1
    4 5
    

    输出样例:8

        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            //N组物品
            int N = sc.nextInt();
            //背包体积
            int bagV = sc.nextInt();
            //s[i]表示第i组有多少件商品
            int[] s = new int[N+1];
            //v[i][j]表示第i组第j件商品的体积
            int[][] v = new int[N+1][];
            //w[i][j]表示第i组第j件商品的价值
            int[][] w = new int[N+1][];
            for(int i = 1; i <= N; i++) {//第i组商品
                s[i] = sc.nextInt();
                v[i] = new int[s[i]+1];
                w[i] = new int[s[i]+1];
                for(int j = 1; j <= s[i]; j++) {
                    v[i][j] = sc.nextInt();
                    w[i][j] = sc.nextInt();
                }
            }
            
            System.out.println(groupBag(N, bagV, s, v, w));
    
        }
    //一组商品只能选一个,相当于0-1背包问题 public static int groupBag(int N, int bagV, int[] s, int[][] v, int[][] w) { //f[j]表示背包容量为j时的最大价值 int[] f = new int[bagV+1]; for(int i = 1; i <= N; i++){ for(int j = bagV; j >=0; j--) { //选第i组物品的第k件商品 for(int k = 1; k <= s[i]; k++) { if(j >= v[i][k]) f[j] = Math.max(f[j], f[j-v[i][k]]+w[i][k]); } } } return f[bagV]; }

    7、背包问题求方案数

    问题描述:

      有 N件物品和一个容量是 V的背包。每件物品只能使用一次。第 i 件物品的体积是 vi,价值是 wi。

      求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最优选法的方案数。注意答案可能很大,请输出答案模 109+7 的结果。

    输入格式:
      第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
      接下来有 N行,每行两个整数 vi,wi,用空格隔开,分别表示第 i件物品的体积和价值。

    输出格式:
      输出一个整数,表示 方案数 模 109+7 的结果。

    输入样例:
    4 5
    1 2
    2 4
    3 4
    4 6
    输出样例:2

        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int N = sc.nextInt(); //N个物品
            int bagV = sc.nextInt(); //背包容积为bagV
            //存储物品的体积和价值
            int[] v = new int[N+1]; //体积
            int[] w = new int[N+1]; //价值
            for(int i = 1; i <= N; i++) {
                v[i] = sc.nextInt();
                w[i] = sc.nextInt();
            }
            System.out.println(numsOfBag(N, bagV, v, w));
        }
        
        /**最优方案总数,指物品总价值最大的方案数。*/
        public static int numsOfBag(int N, int bagV, int[] v, int[] w) {
            //f[j]表示背包容量为j时的最大价值
            int[] f = new int[bagV+1];
            //num[j]表示背包容量为j时的最大方案数
            int[] num = new int[bagV+1];
            Arrays.fill(num, 1);//f[]都初始化为1
            
            final int mod = 10000007;
            
            for(int i = 1; i <= N; i++) {
                for(int j = bagV; j >= v[i]; j--) {
                    //如果加入该商品价值更大,必然加入该商品,因为是必然,所以这样的方案数量不变
                    if(f[j] < f[j-v[i]]+w[i]){
                        num[j] = num[j-v[i]];
                        num[j] %= mod;
                    }
                    //如果加入该商品与不加的价值相等,那么加或不加都可以,都是一种方案,所以方案数相加
                    else if(f[j] == f[j-v[i]]+w[i]){
                        num[j] += num[j-v[i]];
                        num[j] %= mod;
                    }
                    //如果加入该商品价值更小,那么肯定不加,方案数保持num[i-1][j]即可
                    
                    //统一更新f[j]
                    f[j] = Math.max(f[j], f[j-v[i]]+w[i]);
                }
            }
            return num[bagV];
        }

    8、背包问题求具体方案

    题目描述:

      有 N件物品和一个容量是 V 的背包。每件物品只能使用一次。第 i 件物品的体积是 vi,价值是 wi。
      求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出字典序最小的方案。这里的字典序是指:所选物品的编号所构成的序列。物品的编号范围是 1…N。

    输入格式:
      第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。
      接下来有 N行,每行两个整数 vi,wi,用空格隔开,分别表示第 i件物品的体积和价值。
    输出格式:
      输出一行,包含若干个用空格隔开的整数,表示最优解中所选物品的编号序列,且该编号序列的字典序最小。物品编号范围是 1…N。

    输入样例:
    4 5
    1 2
    2 4
    3 4
    4 6
    输出样例:1 4

        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            int N = sc.nextInt(); //N个物品
            int bagV = sc.nextInt(); //背包容积为bagV
            //存储物品的体积和价值
            int[] v = new int[N+1]; //体积
            int[] w = new int[N+1]; //价值
            ///////因为要求字典序最小,我们把输入逆序,然后提供一个记录物品序号的数组index
            int[] index = new int[N+1];
            int indexTemp = 0;
            ////输入逆序
            for(int i = N; i >= 1; i--) {
                v[i] = sc.nextInt();
                w[i] = sc.nextInt();
                /////////
                index[i] = ++indexTemp;
            }
            
            List<Integer> list = progectOfBag(N, bagV, v, w,index);
            for(Integer item : list)
                System.out.print(item + " ");
            
        }
        
        public static List<Integer> progectOfBag(int N, int bagV, int[] v, int[] w, int[] index) {
            
            //首先按0-1背包问题求最大价值,这里二维实现,f[i][j]表示背包容量为j时前i-1个物品的最大价值
            int[][] f = new int[N+1][bagV+1];
            for(int i = 1; i <= N; i++) {
                for(int j = 0; j <= bagV; j++) {
                    if(j >= v[i])
                        f[i][j] = Math.max(f[i-1][j], f[i-1][j-v[i]]+w[i]);
                    else
                        f[i][j] = f[i-1][j];
                }
            }
            
            //存方案
            List<Integer> list = new ArrayList<Integer>();
            //反推方案
            int vol = bagV;
            //从最后一个往前推
            for(int i = N; i >= 1; i--) {
                if(vol >= v[i] && f[i][vol] == f[i-1][vol-v[i]]+w[i]){
                    //说明选择了当前物品
                    list.add(index[i]);
                    vol -= v[i];
                }
                if(vol <= 0)
                    break;    
            }
            return list;
        }

    9、一个类似背包问题的问题,求无价值的所有方案

    题目描述:

      假设有一个能装入总体积为bagV的背包和 N件体积分别为v1,v2 , … , vn的物品,能否从N件物品中挑选若干件恰好装满背包,即使v1+v2+…+vn=bagV,要求找出所有满足上述条件的解。

    输入格式:
      第一行两个整数,N,bagV,用空格隔开,分别表示物品数量和背包容积。
      接下来一行有N个整数,用空格隔开,分别表示第 i件物品的体积vi。
    输出格式:
      输出具体方案

    输入示例:
    6 10
    1 8 4 3 5 2
    输出:
    1 4 3 2
    1 4 5
    8 2
    3 5 2

    注意:这个做法只适合N<32的情况,因为1<<32对int型变量会溢出。   1L<<x的话x的最大值为63

        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            //物品个数
            int N = sc.nextInt();
            //背包体积
            int bagV = sc.nextInt();
            //物品体积
            int[] v = new int[N];
            for(int i = 0; i < N; i++)
                v[i] = sc.nextInt();
            
            fill(v, N, bagV);
        }
        /*
            用1到2^N的二进制来求解,若二进制数该位置是1,则将其取出求和: 1表示成选取状态, 0表示成未选取状态。
            标记中有几个 1就是代表选取了几个数,然后再去遍历这些 1所有可能存在的排列方式,最后做一个判断,这个判断就是:
            每一种排列方式,都代表着数组中不同位置的被选中的数的组合,所以这里就是将选中的这些数字进行求和运算,然后判断求出的和是不是等于bagV 。
         */
        public static void fill(int[] v, int N, int bagV) {
            //从1循环到2^N,相当于对v从00...01一直循环到11...11
            for(int i = 1; i <= 1 << N; i++){
                int sum = 0;
                String temp = "";
                for(int j = 0; j < N; j++) {
                    //用i与2^j进行位与运算,若结果不为0,则表示第j位不为0,从数组中取出第j个数
                    if((i & 1 << j) != 0) {
                        sum += v[j];
                        temp += v[j] + " ";
                    }    
                }
                if(sum == bagV)
                    System.out.println(temp);
            }
        }    

    参考:dd大牛的《背包九讲》

    代码练习:https://www.acwing.com/problem/

  • 相关阅读:
    第二阶段个人冲刺总结01
    软件工程学习进度表13
    软件工程学习进度表12
    个人博客(09)
    个人博客(07)
    个人博客(08)
    poj1562 DFS入门
    poj3278 BFS入门
    数组单步运算
    十天冲刺
  • 原文地址:https://www.cnblogs.com/toria/p/11316377.html
Copyright © 2011-2022 走看看