蒜头君的购物袋 - 01背包问题

蒜头君去超市购物,他有一只容量为 V 的购物袋,同时他买了 n件物品,已知每件物品的体积 vi。蒜头君想知道,挑选哪些物品放入购物袋中,可以使袋子剩余的空间最小。

输入格式

第一行输入一个整数 V1≤V≤20,000),表示购物袋的容量。

第二行输入一个整数 n1≤n≤30),表示蒜头君购买的n件物品。

接下来输入n行,每行输入一个整数 vi1≤vi≤10,000),表示第i件物品的体积。

输出格式

输出一行,输出一个整数,表示购物袋最小的剩余空间。

样例输入
20
5
7
5
7
3
7
样例输出
1

动态规划中背包问题,几乎相当于没有改。

剩下的最小的空间 = V - 能装的最大的空间。

而且这题的每个物品的价值就相当于他的体积,都省的建两个数组了。

状态转移方程:f[i][j] = Math.max(f[i - 1][j], f[i - 1][j - p[i]] + p[i])

*f[i][j]表示在容量为 j 的情况下能装下的 i 个物品中的最大体积数

Java代码:

public class Main {

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        int V = in.nextInt(), n = in.nextInt();
        int[] p = new int[n + 1];
        for(int i = 1; i <= n; i++) {
            p[i] = in.nextInt();
        }
        in.close();
        
        int[][] f = new int[n + 1][V + 1];
        
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= V; j++) {
                if(p[i] <= j) {
                    f[i][j] = Math.max(f[i - 1][j], f[i - 1][j - p[i]] + p[i]);
                }else {
                   f[i][j] = f[i - 1][j];
                }
            }
        }       
        System.out.println(V - f[n][V]);
    }

}

另附上标准01背包问题代码:

* v 和 p 分别为表示体积数组与表示价值数组

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int V = in.nextInt(), n = in.nextInt();
        int[] v = new int[n + 1];
        int[] p = new int[n + 1];
        for(int i = 1; i <= n; i++) {
            v[i] = in.nextInt();
            p[i] = in.nextInt();
        }
        in.close();
        
        int[][] f = new int[n + 1][V + 1];
        
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= V; j++) {
                if(v[i] <= j) {
                    f[i][j] = Math.max(f[i - 1][j], f[i - 1][j - v[i]] + p[i]);
                }else {
                    f[i][j] = f[i - 1][j];
                }
            }
        }
        
        System.out.println(f[n][V]);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值