背包問題


  • 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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM