Backpack model of Pokemon's subduing Yan's DP analysis method Java

First off topic :

diver

Title description :

Pokemon is a story about Xiaozhi and his partner Pikachu taking an adventure together.

One day, Xiaozhi and Pikachu came to the Pokemon Hunting Ground, where there are many precious wild Pokemon.

Xiaozhi also wants to subdue some of the elves. However, wild elves are not so easy to be subdued.

For each wild elf, Xiaozhi may need to use many poke balls to conquer it, and in the process of conquering, the wild elf will also cause certain damage to Pikachu (thus reducing Pikachu's physical strength).

When Pikachu's physical strength is less than or equal to 0, Xiaozhi must end the hunt (because he needs to heal Pikachu), and the wild elves with Pikachu's physical strength less than or equal to 0 will not be subdued by Xiaozhi.

When Xiaozhi's pokeball ran out, the hunt was over.

We assume that Xiaozhi has two choices when encountering a wild elf: conquer it or leave it.

If Xiaozhi chooses to conquer, then he will definitely throw a poke ball that can subdue the elf, and Pikachu will definitely suffer corresponding damage; if he chooses to leave it, then Xiaozhi will not lose the poke ball, and Pikachu will not lose. physical strength.

Xiaozhi has two goals: the main goal is to conquer as many wild elves as possible; if the number of elves that can be conquered is the same, Xiaozhi hopes that Pikachu will suffer less damage (the more stamina remaining), because they have to continue. adventure.

Now we know the number of Elf Balls and Pikachu's initial physical strength, and we know the number of Elf Balls that each Elf needs to conquer and the number of damage it will cause Pikachu in the process of being conquered.

Excuse me, how can Xiaozhi choose which elves to subdue to achieve his goal?

Input format

The first line of input data contains three integers: N, M, K, which represent the number of pixie balls, Pikachu's initial physical strength, and the number of wild elves, respectively.

In the next K rows, each row represents a wild elf, including two integers: the number of elf balls needed to conquer the elf, and the damage caused to Pikachu during the conquest.
Output format

The output is one line, containing two integers: C and R, respectively, indicating that at most C elves are conquered, and Pikachu's remaining stamina is at most R when conquering C elves.

data range

0<N≤1000,
0<M≤500,
0<K≤100

Input example 1:

10 100 5
7 10
2 40
2 50
1 20
4 20

Sample output 1:

3 30

Input example 2:

10 100 5
8 110
12 10
20 10
5 200
1 110

Output sample 2:

0 100

Ideas :

1.很典型的二维背包费用问题,设状态方程为dp[k][n][m],表示前k个小精
灵花费精灵球为n,体力为m时最多能收服的小精灵数量;

2.要求剩余的最多的体力,根据状态定义可知,当k和n固定的时候,不断减
少体力看是否跟最大值相等;

3.当皮卡丘的体力小于等于0时,小智就必须结束狩猎(因为他需要给皮卡丘疗伤),而使得皮卡丘体力小于等于0的野生小精灵也不会被小智收服,意思就是
最多能用的体力为M-1

Code :


import java.util.Scanner;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner input=new Scanner(System.in);
        //N,M,K,分别代表小智的精灵球数量、皮卡丘初始的体力值、野生小精灵的数量。
        int N=input.nextInt();
        int M=input.nextInt();
        int K=input.nextInt();
        int []weight=new int[K+1];//数量
        int []value=new int[K+1];//消耗体力
        for(int i=1;i<=K;i++){
    
    
            weight[i]=input.nextInt();
            value[i]=input.nextInt();
        }
        int [][][]dp=new int[K+1][N+1][M+1];
        int max=0;
        for(int i=1;i<=K;i++)
            for(int j=1;j<=N;j++){
    
    
                for(int k=1;k<M;k++){
    
    
                        if(j<weight[i]||k<value[i])
                            dp[i][j][k]=dp[i-1][j][k];
                        else
                        {
    
    
                            dp[i][j][k]=Math.max(dp[i-1][j][k],dp[i-1][j-weight[i]][k-value[i]]+1);
                        }
                        max=Math.max(max,dp[i][j][k]);
                }
            }
            int k=M-1;
            while(k>0&&max==dp[K][N][k-1]){
    
    
                k--;
            }
        System.out.println(max+" "+(M-k));

    }
}

Optimized version :


import java.util.Scanner;

public class Main {
    
    
    public static void main(String[] args) {
    
    
        Scanner input=new Scanner(System.in);
        //N,M,K,分别代表小智的精灵球数量、皮卡丘初始的体力值、野生小精灵的数量。
        int N=input.nextInt();
        int M=input.nextInt();
        int K=input.nextInt();
        int []weight=new int[K+1];//数量
        int []value=new int[K+1];//消耗体力
        for(int i=1;i<=K;i++){
    
    
            weight[i]=input.nextInt();
            value[i]=input.nextInt();
        }
        int [][]dp=new int[N+1][M+1];
        int max=0;
        for(int i=1;i<=K;i++)
            for(int j=N;j>=1;j--){
    
    
                for(int k=M-1;k>=1;k--){
    
    
                        
                        if(j>=weight[i]&&k>=value[i])
                        {
    
    
                            dp[j][k]=Math.max(dp[j][k],dp[j-weight[i]][k-value[i]]+1);
                        }
                        max=Math.max(max,dp[j][k]);
                }
            }
            int k=M-1;
            while(k>0&&max==dp[N][k-1]){
    
    
                k--;
            }
        System.out.println(max+" "+(M-k));

    }
}

Guess you like

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