华为OD机试-2024年E卷-最大报酬[100分] JAVA

解法:类似01背包的动态规划问题,代码如下

public class OJTest7 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int timeCount = in.nextInt();
        int jobNums = in.nextInt();
        in.nextLine();
        int[] costTimes = new int[jobNums];
        int[] rewards = new int[jobNums];
        for (int i = 0; i < jobNums; i++) {
            String[] inputs = in.nextLine().split(" ");
            costTimes[i] = Integer.parseInt(inputs[0]);
            rewards[i] = Integer.parseInt(inputs[1]);
        }
        calculateReward(jobNums, timeCount, costTimes, rewards);
        calculateReward2(jobNums, timeCount, costTimes, rewards);
    }

    private static void calculateReward(int jobNums, int timeCount, int[] costTimes, int[] rewards) {
        //实际上是一个动态规划的问题,类似01背包问题。 n项工作,选择做哪项或者不做
        //定义一个dp[jobNums+1][timeCount+1], 数组的行代表的是工作时长,从0开始,列代表的是工作的数量,dp[i][j]的值是获得的报酬;
        int[][] dp = new int[jobNums + 1][timeCount + 1];
        for (int i = 1; i < jobNums + 1; i++) {
            for (int j = 1; j < timeCount + 1; j++) {
                dp[i][j] = dp[i - 1][j]; // 不选择当前工作的情况
                if (j >= costTimes[i - 1]) {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - costTimes[i - 1]] + rewards[i - 1]);
                }
            }
        }
        System.out.println(dp[jobNums][timeCount]);
    }

    private static void calculateReward2(int jobNums, int timeCount, int[] costTimes, int[] rewards) {
        //一维dp解法
        int[] dp = new int[timeCount + 1];
        for (int i = 0; i < jobNums; i++) {
            for (int j = timeCount; j >= costTimes[i]; j--) { //倒序遍历的原因是外层i记录的dp上一轮的计算结果不会被覆盖,正序覆盖计算结果就不对了,二维dp可以正序
                dp[j] = Math.max(dp[j], dp[j - costTimes[i]] + rewards[i]);
            }
        }
        System.out.println(dp[timeCount]);
    }
}

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务