背包问题初接触

来源:互联网 发布:ubuntu输入法不对 编辑:程序博客网 时间:2024/06/07 06:55

ZeroOnePack

  有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。

ZeroOnePack.txt

3 10 #(物品个数,背包容量)6 6 #(体积,价值)6 71 2
import java.io.InputStream;import java.util.Scanner;/** * 有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。 */public class ZeroOnePack {    public static void main(String[] args) throws Exception {        getMaxValue();    }    /**     * 3 10     * 3 4     * 4 5     * 5 6     *     * @return     * @throws Exception     */    public static int getMaxValue() throws Exception {        int maxValue = 0;        InputStream is = ZeroOnePack.class.getClassLoader().getResourceAsStream("algorithm/bag/bag01/ZeroOnePack.txt");        Scanner scanner = new Scanner(is);        int N = scanner.nextInt();//物品个数        int V = scanner.nextInt();//背包容量        int[] c = new int[N + 1];//物品体积,默认初始化为0,为了方便理解角标从1开始        int[] w = new int[N + 1];//物品价值        int[] f = new int[V + 1];//存储结果        for (int k = 1; k <= 3; k++) {            c[k] = scanner.nextInt();            w[k] = scanner.nextInt();        }        /**         * 理解:         * f[i][v] = max {f[i][v],f[i-1][v-c[i]]+w[i]}         * 优化:         * f[v] = max{f[v],f[v-c[i]]+w[i]}         */        showF(f);        //n件物品        for (int i = 1; i <= N; i++) {            // 第i件物品。比较放入后(占v份空间下的价值)与不放(原来i-1物品占v份空间)价值大小            for (int v = V; v >= c[i]; v--) {                if (f[v - c[i]] + w[i] > f[v]) {                    f[v] = f[v - c[i]] + w[i];                }                showF(f);            }        }        //showF(f);        return maxValue;    }    public static void showF(int[] f) {        for (int k = 1; k < f.length; k++) {            System.out.printf("%d\t", f[k]);        }        System.out.println();    }}

输出

0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   6   0   0   0   0   0   0   0   0   6   6   0   0   0   0   0   0   0   6   6   6   0   0   0   0   0   0   6   6   6   6   0   0   0   0   0   6   6   6   6   6   0   0   0   0   0   6   6   6   6   7   0   0   0   0   0   6   6   6   7   7   0   0   0   0   0   6   6   7   7   7   0   0   0   0   0   6   7   7   7   7   0   0   0   0   0   7   7   7   7   7   0   0   0   0   0   7   7   7   7   9   0   0   0   0   0   7   7   7   9   9   0   0   0   0   0   7   7   9   9   9   0   0   0   0   0   7   9   9   9   9   0   0   0   0   0   7   9   9   9   9   0   0   0   0   2   7   9   9   9   9   0   0   0   2   2   7   9   9   9   9   0   0   2   2   2   7   9   9   9   9   0   2   2   2   2   7   9   9   9   9   2   2   2   2   2   7   9   9   9   9   

CompletePack

  有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
  
CompletePack.txt

3 10 #(物品个数,背包容量)6 6 #(体积,价值)6 71 2
import java.io.InputStream;import java.util.Scanner;/** * 完全背包 * 有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。 * 求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。 */public class CompletePack {    public static void main(String[] args) throws Exception {        getMaxValue();    }    /**     * 3 10     * 3 4     * 4 5     * 5 6     *     * @return     * @throws Exception     */    public static int getMaxValue() throws Exception {        int maxValue = 0;        InputStream is = CompletePack.class.getClassLoader().getResourceAsStream("algorithm/bag/complete/CompletePack.txt");        Scanner scanner = new Scanner(is);        int N = scanner.nextInt();//物品种类数目        int V = scanner.nextInt();//背包容量        int[] c = new int[N + 1];//物品体积,默认初始化为0,为了方便理解角标从1开始        int[] w = new int[N + 1];//物品价值        int[] f = new int[V + 1];//存储结果        for (int k = 1; k <= 3; k++) {            c[k] = scanner.nextInt();            w[k] = scanner.nextInt();        }        /**         * 理解:         * f[i][v] = max {f[i][v],f[i-1][v-c[i]]+w[i]}         * 优化:         * f[v] = max{f[v],f[v-c[i]]+w[i]}         */        showF(f);        //n件物品        for (int i = 1; i <= N; i++) {            // 第i件物品。比较放入后(占v份空间下的价值)与不放(原来i-1物品占v份空间)价值大小//            for (int v = V; v >= c[i]; v--) {//逆序是ZeroOnePack            for (int v = c[i]; v <= V; v++) {//顺序是CompletePack                if (f[v - c[i]] + w[i] > f[v]) {                    f[v] = f[v - c[i]] + w[i];                }                showF(f);            }        }        //showF(f);        return maxValue;    }    public static void showF(int[] f) {        for (int k = 1; k < f.length; k++) {            System.out.printf("%d\t", f[k]);        }        System.out.println();    }}

中间运行结果

0   0   0   0   0   0   0   0   0   0   0   0   4   0   0   0   0   0   0   0   0   0   4   4   0   0   0   0   0   0   0   0   4   4   4   0   0   0   0   0   0   0   4   4   4   8   0   0   0   0   0   0   4   4   4   8   8   0   0   0   0   0   4   4   4   8   8   8   0   0   0   0   4   4   4   8   8   8   12  0   0   0   4   4   4   8   8   8   12  12  0   0   4   5   4   8   8   8   12  12  0   0   4   5   5   8   8   8   12  12  0   0   4   5   5   8   8   8   12  12  0   0   4   5   5   8   9   8   12  12  0   0   4   5   5   8   9   10  12  12  0   0   4   5   5   8   9   10  12  12  0   0   4   5   5   8   9   10  12  13  0   0   4   5   6   8   9   10  12  13  0   0   4   5   6   8   9   10  12  13  0   0   4   5   6   8   9   10  12  13  0   0   4   5   6   8   9   10  12  13  0   0   4   5   6   8   9   10  12  13  0   0   4   5   6   8   9   10  12  13

MultiplePack

  有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

MultiplePack .txt

#第一组3 103 4 14 5 15 6 1#第二组3 103 4 104 5 105 6 10
import java.util.Scanner;import static java.lang.Math.max;import static java.lang.Math.min;/** * 多重背包 * <p> * 有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。 * 求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。 */public class MultiplePack {    public static void main(String[] args) {        getMaxValue();    }    public static int getMaxValue() {        int maxValue = 0;        Scanner scanner = new Scanner(MultiplePack.class.getClassLoader().getResourceAsStream(                "algorithm/bag/multiple/MultiplePack.txt"));        int N = scanner.nextInt();//物品种类数目        int V = scanner.nextInt();//背包的容量        int[] c = new int[N + 1];//c[i]表示第i种物品的费用        int[] w = new int[N + 1];//w[i]表示第i种物品的价值        int[] n = new int[N + 1];//n[i]表示第i种物品的数量        int[] f = new int[V + 1];//f[]记录每次操作中间过程        for (int k = 1; k <= N; k++) {            c[k] = scanner.nextInt();            w[k] = scanner.nextInt();            n[k] = scanner.nextInt();        }        /**         * 多重背包转成01背包         * */        for (int i = 1; i <= N; i++) {            /**             * 每种物品的个数,转换成了物品数为Σn[i]的01背包问题             */            for (int j = 1; j <= min(V / c[i], n[i]); j++) {                for (int v = V; v >= c[i]; v--) {                    f[v] = max(f[v], f[v - c[i]] + w[i]);                    showF(f);                }            }        }        return maxValue;    }    public static void showF(int[] f) {        for (int k = 1; k < f.length; k++) {            System.out.printf("%d\t", f[k]);        }        System.out.println();    }}

两组中间结果

0   0   0   0   0   0   0   0   0   4   0   0   0   0   0   0   0   0   4   4   0   0   0   0   0   0   0   4   4   4   0   0   0   0   0   0   4   4   4   4   0   0   0   0   0   4   4   4   4   4   0   0   0   0   4   4   4   4   4   4   0   0   0   4   4   4   4   4   4   4   0   0   4   4   4   4   4   4   4   4   0   0   4   4   4   4   4   4   4   9   0   0   4   4   4   4   4   4   9   9   0   0   4   4   4   4   4   9   9   9   0   0   4   4   4   4   9   9   9   9   0   0   4   4   4   5   9   9   9   9   0   0   4   4   5   5   9   9   9   9   0   0   4   5   5   5   9   9   9   9   0   0   4   5   5   5   9   9   9   11  0   0   4   5   5   5   9   9   11  11  0   0   4   5   5   5   9   10  11  11  0   0   4   5   5   5   9   10  11  11  0   0   4   5   5   6   9   10  11  11  0   0   4   5   6   6   9   10  11  11  -------------------------------------------------------------0   0   0   0   0   0   0   0   0   4   0   0   0   0   0   0   0   0   4   4   0   0   0   0   0   0   0   4   4   4   0   0   0   0   0   0   4   4   4   4   0   0   0   0   0   4   4   4   4   4   0   0   0   0   4   4   4   4   4   4   0   0   0   4   4   4   4   4   4   4   0   0   4   4   4   4   4   4   4   4   0   0   4   4   4   4   4   4   4   8   0   0   4   4   4   4   4   4   8   8   0   0   4   4   4   4   4   8   8   8   0   0   4   4   4   4   8   8   8   8   0   0   4   4   4   8   8   8   8   8   0   0   4   4   4   8   8   8   8   8   0   0   4   4   4   8   8   8   8   8   0   0   4   4   4   8   8   8   8   8   0   0   4   4   4   8   8   8   8   12  0   0   4   4   4   8   8   8   12  12  0   0   4   4   4   8   8   8   12  12  0   0   4   4   4   8   8   8   12  12  0   0   4   4   4   8   8   8   12  12  0   0   4   4   4   8   8   8   12  12  0   0   4   4   4   8   8   8   12  12  0   0   4   4   4   8   8   8   12  12  0   0   4   4   4   8   8   8   12  13  0   0   4   4   4   8   8   8   12  13  0   0   4   4   4   8   8   9   12  13  0   0   4   4   4   8   9   9   12  13  0   0   4   4   4   8   9   9   12  13  0   0   4   4   5   8   9   9   12  13  0   0   4   5   5   8   9   9   12  13  0   0   4   5   5   8   9   9   12  13  0   0   4   5   5   8   9   9   12  13  0   0   4   5   5   8   9   10  12  13  0   0   4   5   5   8   9   10  12  13  0   0   4   5   5   8   9   10  12  13  0   0   4   5   5   8   9   10  12  13  0   0   4   5   5   8   9   10  12  13  0   0   4   5   5   8   9   10  12  13  0   0   4   5   5   8   9   10  12  13  0   0   4   5   5   8   9   10  12  13  0   0   4   5   5   8   9   10  12  13  0   0   4   5   5   8   9   10  12  13  0   0   4   5   6   8   9   10  12  13  0   0   4   5   6   8   9   10  12  13  0   0   4   5   6   8   9   10  12  13  0   0   4   5   6   8   9   10  12  13  0   0   4   5   6   8   9   10  12  13  0   0   4   5   6   8   9   10  12  13  0   0   4   5   6   8   9   10  12  13  
原创粉丝点击