Diver Yan's DP Analysis Method Java of Backpack Model

First off topic :

Pokemon Reap

Title description :

Divers must use special equipment for diving.

He has a cylinder with two types of gases: one for oxygen and one for nitrogen.

Various amounts of oxygen and nitrogen are required for the depth to which divers can dive.

The diver has a certain number of cylinders. Each cylinder has a weight and gas capacity.

A diver needs a certain amount of oxygen and nitrogen in order to complete his job.

What is the minimum total weight of the cylinder he needs to complete the job?

Example: The diver has 5 cylinders. The three numbers in each row are: the amount of oxygen and nitrogen (liter) and the weight of the cylinder:

3 36 120

10 25 129

5 50 250

1 45 130

4 20 119

If the diver needs 5 liters of oxygen and 60 liters of nitrogen, the minimum total weight is 249 (1, 2 or 4, 5 cylinders).

Your task is to calculate the lowest value of the cylinder weight that the diver needs to complete his work.

Input format

There are 2 integers m and n in the first line. They represent the required amount of oxygen and nitrogen respectively.

In the second row, the integer k represents the number of cylinders.

The following k lines, each line includes ai, bi, ci, 3 integers. These are: the capacity of oxygen and nitrogen in the i-th cylinder and the cylinder weight.

Output format

Only one line contains an integer, which is the lowest value of the total weight of the cylinders required by the diver to complete the work.

data range

1≤m≤21,
1≤n≤79,
1≤k≤1000,
1≤ai≤21,
1≤bi≤79,
1≤ci≤800

Input sample:

5 60
5
3 36 120
10 25 129
5 50 250
1 45 130
4 20 119

Sample output:

249

Ideas

1.这是典型的二维费用背包问题,只不过状态定义有点不一样,题目要求
的是我们找的是当氧气为n,氮气为m时总重量最低的值,意思就是我们要
在氧气>=n&&氮气>=m的情况下,找最小值。因此我们的状态定义dp[k][i][j]
应该是前k个物品中,氧气含量至少为i,氮气含量至少为j的所有方案的最
小值。

2.“至少”,跟“最多”和“恰好”的区别是:在“至少”的情况下,i,j可以为负!
这个我们所定义的状态并不冲突,只不过氧气或氮气为负数的情况是无法达
到的,要跟为氧气或氮气为零的情况相等;

3.dp[0][0][0]初始化为0,dp[0][j][j]=INF,根据状态定义:0个罐子,
氧气且氮气含量至少为0时,方案数为0,前0个罐子,氧气含量至少为就,
且氮气含量至少为j时,这个方案是不存在的又要找最小值因此设置为INF
(注意这里的INF为0x3f3f3f3f,防止爆int)4.若没有状态优化,必须从氧气和氮气的含量必须从0开始循环,因为氧气
和氮气为负的的情况都要考虑,因此0页也必须考虑;

Insert picture description here

Thank y total video and small foolishly Gangster guide

Code :

import java.util.Scanner;
import java.util.Arrays;

public class Main {
    
    
    static int INF = 0x3f3f3f3f;
    public static void main(String[] args) {
    
    
        Scanner input = new Scanner(System.in);
        int O = input.nextInt();
        int N = input.nextInt();
        int K = input.nextInt();
        int[] oo = new int[K + 1];
        int[] nn = new int[K + 1];
        int[][][] dp = new int[K + 1][O + 1][N + 1];
        int[] arr = new int[K + 1];

        for (int i = 1; i <= K; i++) {
    
    

            oo[i] = input.nextInt();// O
            nn[i] = input.nextInt();// N
            arr[i] = input.nextInt();
        }
        for(int i = 0;i <= K;i ++)
            for (int j = 0; j <= O; j++)
                Arrays.fill(dp[i][j], INF);
        dp[0][0][0] = 0;
        for (int i = 1; i <= K; i++) {
    
    
            for (int j = 0; j <= O; j++) {
    
    
                for (int k = 0; k <= N; k++) {
    
    
                    int t1 = j - oo[i];
                    int t2 = k - nn[i];
                    if (t1 < 0)
                        t1 = 0;
                    if (t2 < 0)
                        t2 = 0;
                    dp[i][j][k] = Math.min(dp[i - 1][t1][t2] + arr[i], dp[i - 1][j][k]);

                }
            }
        }
        System.out.println(dp[K][O][N]);
    }

}


Code (space optimized version)

import java.util.Scanner;
import java.util.Arrays;

public class Main {
    
    
    static int INF = 0x3f3f3f3f;
    public static void main(String[] args) {
    
    
        Scanner input = new Scanner(System.in);
        int O = input.nextInt();
        int N = input.nextInt();
        int K = input.nextInt();
        int[] oo = new int[K + 1];
        int[] nn = new int[K + 1];
        int[][] dp = new int[O + 1][N + 1];
        int[] arr = new int[K + 1];

        for (int i = 1; i <= K; i++) {
    
    

            oo[i] = input.nextInt();// O
            nn[i] = input.nextInt();// N
            arr[i] = input.nextInt();
        }
        for(int i = 0;i <= O;i ++)
              Arrays.fill(dp[i], INF);
              
        dp[0][0] = 0;
        for (int i = 1; i <= K; i++) {
    
    
            for (int j = O; j >=0; j--) {
    
    
                for (int k = N; k>=0; k--) {
    
    
                    int t1 = j - oo[i];
                    int t2 = k - nn[i];
                    if (t1 < 0)
                        t1 = 0;
                    if (t2 < 0)
                        t2 = 0;
                    dp[j][k] = Math.min(dp[t1][t2] + arr[i], dp[j][k]);

                }
            }
        }
        System.out.println(dp[O][N]);
    }

}


Guess you like

Origin blog.csdn.net/qq_44844588/article/details/108539804