POJ-3624-01背包问题

文章目录

1. 问题

有N件物品和一个容积为M的背包
第i件物品的体积是w[i], 价值是d[i]
求解将哪些物品装入背包可以使价值总量和最大
每种物品只有一件,可以选择放或者不放
(N <= 3500, M <= 13000)

2.状态和边界条件

F[i][j]表示取前i种物品,使他们总体积不超过j的最优取法得到的价值总和。
要求F[N][M]
边界:

if(w[1] <= j)
	F[1][j] = d[1];
else 
	F[1][j] = 0;

3. 递推式

用F[i][j]表示取前i种物品,使他们总体积不超过j的最优取法取得的价值总和
递推:

// 取或者不取第i中物品,两者选优
F[i][j] = max(F[i-1][j],F[i-1][j-w[i]]+d[i])

本题如果用记忆型递归,需要一个很大的二维数组,会超内存。
注意到这个二维数组的下一行的值,只用到了上一行的正上方及左边的值,因此可以使用滚动数组的思想,只要一行即可。

POJ-3624-01背包问题

POJ-3624-01背包问题
二维数组会超内存

public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        Scanner in = new Scanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskPoj3624 solver = new TaskPoj3624();
        solver.solve(1, in, out);
        out.close();
    }
    static class TaskPoj3624 {
        public void solve(int testNumber, Scanner in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();
            int w[] = new int[n + 1];
            int d[] = new int[n + 1];
            for (int i = 1; i <= n; i++) {
                w[i] = in.nextInt();
                d[i] = in.nextInt();
            }

            int dp[][] = new int[n + 1][m + 1];
            for (int i = 1; i <= n; i++)
                dp[i][0] = 0;
            for (int i = 1; i <= m; i++) {
                if (w[1] >= i) {
                    dp[1][i] = d[i];
                } else {
                    dp[1][i] = 0;
                }
            }
            for (int i = 2; i <= n; i++) {
                for (int j = 1; j <= m; j++) {
                    dp[i][j] = dp[i - 1][j];
                    if (j >= w[i]) {
                        dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - w[i]] + d[i]);
                    }
                }
            }
            out.println(dp[n][m]);
        }

    }
}

使用一维数组
从右向左递推,不会覆盖上一层仍需要使用的数据

public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        Scanner in = new Scanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskPoj3624 solver = new TaskPoj3624();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskPoj3624 {
        public void solve(int testNumber, Scanner in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();
            int w[] = new int[n + 1];
            int d[] = new int[n + 1];
            for (int i = 1; i <= n; i++) {
                w[i] = in.nextInt();
                d[i] = in.nextInt();
            }

            int dp[] = new int[m + 1];
            for (int j = 0; j <= m; j++) {
                if (j >= w[1]) {
                    dp[j] = d[1];
                } else {
                    dp[j] = 0;
                }
            }
            for (int i = 2; i <= n; i++) {
                for (int j = m; j >= 1; j--) {
                    if (j >= w[i]) {
                        dp[j] = Math.max(dp[j], dp[j - w[i]] + d[i]);
                    }
                }
            }
            out.println(dp[m]);
        }

    }
}
上一篇:新人在JAVA基础学习中关于nextLine()用法的疑问


下一篇:区间大数查询