Poj-3624 背包问题

本文通过四个版本的代码展示了如何逐步优化解决背包问题的过程,从最初的双数组到单数组倒叙优化,有效避免了内存溢出问题。

Poj-3624 背包问题

Poj链接

题目

这里写图片描述

解决代码

这里写图片描述
第一版:

import java.util.Scanner;

public class Main {

    /**
     * 有N件物品,有一个体积为V的背包
     * 第i件物品的费用为c[i],价值是w[i];
     * 问:如何价值最大

     4 6
     1 4
     2 6
     3 12
     2 7
     */


    public static int getMaxWorth(int N, int V, int[] c, int[] v) {
        //记录放第 i 个物品时,空间为  j  时, 其最大价值
        int[][] f = new int[N+1][V + 1];
        //最大价值
        int maxWorth = 0;
        //如果不输入,默认就为0
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= V; j++) {
            //如果空间足够放当前物品
                if (j >= c[i - 1]) {
                    f[i][j] = f[i-1][j] > f[i-1][j - c[i - 1]] + v[i - 1] ? f[i-1][j] : f[i-1][j - c[i - 1]] + v[i - 1];
                }else{
                    f[i][j]=f[i-1][j];
                }
                //System.out.println("放第"+i+"物品"+",空间为"+j+"时,其最大价值为"+f[i][j]);
            }
            if (maxWorth < f[i][V]) {
                maxWorth = f[i][V];
            }
        }
        return maxWorth;
    }


    public static void main(String[] args) {
        //N为物品个数
        // V为体积大小
        int N,V;
        int[] c,v;

        Scanner scanner = new Scanner(System.in);


        //依次输入物品个数和体积大小
        N = scanner.nextInt();
        V = scanner.nextInt();

        c = new int[N];
        v = new int[N];

        //输入物品详情
        for (int i = 0; i < N; i++) {
            c[i] = scanner.nextInt();
            v[i] = scanner.nextInt();
        }

        System.out.println(getMaxWorth(N, V, c, v));
    }
}

输入:
4 6
1 4
2 6
3 12
2 7

放第1物品,空间为1时,其最大价值为4
放第1物品,空间为2时,其最大价值为4
放第1物品,空间为3时,其最大价值为4
放第1物品,空间为4时,其最大价值为4
放第1物品,空间为5时,其最大价值为4
放第1物品,空间为6时,其最大价值为4
放第2物品,空间为1时,其最大价值为4
放第2物品,空间为2时,其最大价值为6
放第2物品,空间为3时,其最大价值为10
放第2物品,空间为4时,其最大价值为10
放第2物品,空间为5时,其最大价值为10
放第2物品,空间为6时,其最大价值为10
放第3物品,空间为1时,其最大价值为4
放第3物品,空间为2时,其最大价值为6
放第3物品,空间为3时,其最大价值为12
放第3物品,空间为4时,其最大价值为16
放第3物品,空间为5时,其最大价值为18
放第3物品,空间为6时,其最大价值为22
放第4物品,空间为1时,其最大价值为4
放第4物品,空间为2时,其最大价值为7
放第4物品,空间为3时,其最大价值为12
放第4物品,空间为4时,其最大价值为16
放第4物品,空间为5时,其最大价值为19
放第4物品,空间为6时,其最大价值为23

但是当把此代码提交上去后会出现内存不足的情况。Memory Limit Exceeded

当时就考虑了下可能是因为创建数组 int[][] f = new int[N+1][V + 1]; 过大的原因

因为我们只需要记录两次就可以了,因为只用到了第i,和第i-1;所以修改代码

第二版:

import java.util.Scanner;

public class Main {

    /**
     * 有N件物品,有一个体积为V的背包
     * 第i件物品的费用为c[i],价值是w[i];
     * 问:如何价值最大
     * <p>
     * <p>
     * <p>
     4 6
     1 4
     2 6
     3 12
     2 7
     */


    public static int getMaxWorth(int N, int V, int[] c, int[] v) {
        x=new int[V+1];
        f = new int[V + 1];
        int maxWorth = 0;
        //如果不输入,默认就为0
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= V; j++) {
                if (j >= c[i - 1]) {
                    f[j] = x[j] > x[j - c[i - 1]] + v[i - 1] ? x[j] : x[j - c[i - 1]] + v[i - 1];
                }
//                System.out.println("放"+i+"件物品,当背包体积为"+j+"时,价值为:"+f[j]);
            }
            copy(f,x);
            if (maxWorth < f[V]) {
                maxWorth = f[V];
            }

        }
        return maxWorth;
    }
    public  static void copy(int[] f,int[]x){
        for (int i = 0; i < f.length; i++) {
            x[i]=f[i];
        }
    }

    //N为物品个数
    // V为体积大小
    static int N, V;
    static int[] c, v;
    static int[] f,x;
    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);


        //依次输入物品个数和体积大小
        N = scanner.nextInt();
        V = scanner.nextInt();

        c = new int[N];
        v = new int[N];

        //输入物品详情
        for (int i = 0; i < N; i++) {
            c[i] = scanner.nextInt();
            v[i] = scanner.nextInt();
        }

        System.out.println(getMaxWorth(N, V, c, v));
    }
}

此时就可以Accept了,所以在创建数组一定不能过大,或者说每个数组都要有其作用。不用就要将其释放。

第三版:

单数组倒叙版:

public class Main {

    /**
     * 有N件物品,有一个体积为V的背包
     * 第i件物品的费用为c[i],价值是w[i];
     * 问:如何价值最大
     * <p>
     * <p>
     * <p>
     4 6
     1 4
     2 6
     3 12
     2 7
     */


    public static int getMaxWorth(int N, int V, int[] c, int[] v) {
        int[]  f=new int[V+1];
        int maxWorth = 0;
        //如果不输入,默认就为0
        for (int i = 1; i <= N; i++) {
            for (int j = V; j>=c[i-1]; j--) {
                    f[j] = Math.max(f[j],f[j - c[i - 1]]+v[i-1]);
//                System.out.println("放"+i+"件物品,当背包体积为"+j+"时,价值为:"+f[j]);
            }
            if (maxWorth < f[V]) {
                maxWorth = f[V];
            }

        }
        return maxWorth;
    }
    public  static void copy(int[] f,int[]x){
        for (int i = 0; i < f.length; i++) {
            x[i]=f[i];
        }
    }

    //N为物品个数
    // V为体积大小

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);


        //依次输入物品个数和体积大小
        int  N = scanner.nextInt();
        int  V = scanner.nextInt();

        int[] c = new int[N];
        int[] v = new int[N];

        //输入物品详情
        for (int i = 0; i < N; i++) {
            c[i] = scanner.nextInt();
            v[i] = scanner.nextInt();
        }

        System.out.println(getMaxWorth(N, V, c, v));
    }
}

第四版:和第三版相同
对于数组名称进行整理

import java.util.Scanner;


public class Main {

    /**
     * 有N件物品,有一个体积为V的背包
     * 第i件物品的费用为c[i],价值是w[i];
     * 问:如何价值最大
     * <p>
     * <p>
     * <p>
     4 6
     1 4
     2 6
     3 12
     2 7
     */


    public static int getMaxWorth(int N, int V, int[] c, int[] v) {
        int[]  f=new int[V+1];
        int maxWorth = 0;
        //如果不输入,默认就为0
        for (int i = 1; i <= N; i++) {
            for (int j = V; j>=c[i]; j--) {
                    f[j] = Math.max(f[j],f[j - c[i]]+v[i]);
//                System.out.println("放"+i+"件物品,当背包体积为"+j+"时,价值为:"+f[j]);
            }
            if (maxWorth < f[V]) {
                maxWorth = f[V];
            }

        }
        return maxWorth;
    }

    //N为物品个数
    // V为体积大小

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);


        //依次输入物品个数和体积大小
        int  N = scanner.nextInt();
        int  V = scanner.nextInt();

        int[] n = new int[N+1];
        int[] v = new int[N+1];

        //输入物品详情
        for (int i = 1; i <=N; i++) {
            n[i] = scanner.nextInt();
            v[i] = scanner.nextInt();
        }

        System.out.println(getMaxWorth(N, V, n, v));
    }
}

背包问题大神

dd_engi 的背包九讲:http://blog.youkuaiyun.com/u011439362/article/details/9612127

写在最后

数组使用注意释放,或者在其创建就需要注意内存溢出问题。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值