「背包问题-步入」失衡天平

失衡天平

https://ac.nowcoder.com/acm/contest/24213/1021

题目描述

终于Alice走出了大魔王的陷阱,可是现在傻傻的她忘了带武器了,这可如何是好???这个时候,一个神秘老人走到她面前答应无偿给她武器,但老人有个条件,需要将所选武器分别放在天平的两端,若天平平衡则可以将天平上的所有武器拿走,还好这个天平锈迹斑斑,只要两端重量相差小于等于m就会保持平衡,Alice傻傻的认为越重的武器越好,求Alice最多能拿走的武器总重量。(不限操作次数)

输入描述

第一行2个整数 n, m;
第二行n个整数x,分别表示n件武器的重量。
1 <= n <= 100; 0 <= m <= 100; 1 <= x <= 100;

输出描述

一个整数,表示Alice最多能拿走的武器总重量。

样例

#1

5 4
1 5 61 65 100
132

可以称两次,第1次:(1 ; 5),第二次(61 ; 65)。

#2

5 0
10 20 30 40 100
200

称一次,(10,20,30,40 ; 100)。

提示

解析

为了便于操作,造数据如下:

4 2
1 2 4 5
12

DP 信息:

  • 原问题:将一堆物品分成两堆,他们的天平差不能超过 m,求最大重量
  • 子问题:求前 i 个物品,满足天平差 j 下的最大值
  • DP 定义: d p [ i ] [ j ] dp[i][j] dp[i][j] 将前 i 个物品进行天平的摆放,天平差为 j 时的最大重量
  • DP 方程:有三种情况
    • 不放: d p [ i ] [ j ] = m a x ( d p [ i ] [ j ] , d p [ i − 1 ] [ j ] ) dp[i][j] = max(dp[i][j], dp[i-1][j]) dp[i][j]=max(dp[i][j],dp[i1][j])
    • 放右边: d p [ i ] [ j + W [ i ] ] = m a x ( d p [ i ] [ j + W [ i ] ] , d p [ i − 1 ] [ j ] + W [ i ] ) dp[i][j+W[i]] = max(dp[i][j+W[i]], dp[i-1][j] + W[i]) dp[i][j+W[i]]=max(dp[i][j+W[i]],dp[i1][j]+W[i])
    • 放左边: d p [ i ] [ j − W [ i ] ] = m a x ( d p [ i ] [ j − W [ i ] ] , d p [ i − 1 ] [ j ] + W [ i ] ) dp[i][j-W[i]] = max(dp[i][j-W[i]], dp[i-1][j] + W[i]) dp[i][jW[i]]=max(dp[i][jW[i]],dp[i1][j]+W[i])

1644771848107

解释DP的第二维,天平差为 j 是的最大重量:

dp[2][1] = 3 // 放入前2个物品,天平差为1时,最大值为3
那么如何体现这句话呢?
先将前2个物品进行天平摆放:
	(1)+(2) // 天平差为1,最大值为3

dp[2][2] = 2 // 放入前2个物品,天平差为2时,最大值为2
	(0)+(2) // 天平差为2,最大值为2

dp[3][1] = 7 // 放入前3个物品,天平差为1时,最大值为7
	(1+2)+(4)=7 // 天平差为1,最大值为7

dp[3][2] = dp[2][2] + 4 = 6
	dp[3][2] = max(dp[3][2], dp[2][2]);
	dp[3][2+4] = max(dp[3][2+4], dp[2][2+4] + W[3]);
	dp[3][abs(2-4)] = max(dp[3][2], dp[2][2] + W[3]); // 2+4
	// 前面dp[2][2]已经把前2个物品在天平差为2时的最大值计算好了
	// 我们现在只是新加一个物品,因此在此基础上加上当前的物品重量即可。

d p [ 3 ] [ 1 ] = 7 dp[3][1]=7 dp[3][1]=7 为例,解释如何来的:

i = 3, j = 3, W[3] = 4
不放:dp[3][3] = max(dp[3][3], dp[2][3]);
放右边:dp[3][7] = max(dp[3][7], dp[2][7] + W[3]);
放左边:dp[3][1] = max(dp[3][1], dp[2][1] + W[3]); // 3(原本是3), 3+4

AC Code

import java.util.*;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), m = sc.nextInt();
        int[] W = new int[10005];
        int[][] dp = new int[105][10005];
        int sum = 0;
        
        for(int i = 1; i <= n; i++) {
    
    
            W[i] = sc.nextInt();
            sum += W[i];
        }
        
        for(int i = 0; i <= n; i++) Arrays.fill(dp[i], -0x8f);
        
        dp[0][0] = 0;
        
        for(int i = 1; i <= n; i++) {
    
    
            for(int j = 0; j <= sum; j++) {
    
    
                dp[i][j] = Math.max(dp[i][j], dp[i-1][j]);
                if(j + W[i] <= sum) dp[i][j+W[i]] = Math.max(dp[i][j+W[i]], dp[i-1][j] + W[i]);
                dp[i][Math.abs(j-W[i])] = Math.max(dp[i][Math.abs(j-W[i])], dp[i-1][j] + W[i]);
            }
        }
        
        int ans = 0;
        
        for(int i = 0; i <= m; i++) {
    
    
            ans = Math.max(ans, dp[n][i]);
        }
        
        System.out.println(ans);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43098197/article/details/130356703