【华为机试真题详解 Java实现】攻城战【2023 Q1 考试题 A卷 200分】

这篇博客详细解析了华为2023年第一季度机试真题——攻城战,涉及Java编程实现。通过动态规划解决背包问题的变体,求解在给定时间内或火药耗尽前的最大打击威力。文章介绍了问题背景、输入输出描述、解题思路,并给出了参考代码。
摘要由CSDN通过智能技术生成

题目描述

【攻城战】

一支攻城部队,有若干种大炮各座,以及数量有限的火药,每种大炮的威力不尽相同,且在每次开火之前都需要一定时间填充火药,
请你帮助指挥官在给定的时间结束之前或者火药存量耗尽之前给予城池最大的打击。

约束条件:
大炮每次开火的威力一样;
火药剩余量不小于大炮的消耗量,该大炮才能开火;
填充火药之外的时间忽略不计;
不同种大炮可以同时开火。

输入描述

第一行,整数N,M,T
N表示大炮种类个数
M表示火药总量
T表示攻城总时间
1<= N,M,T<= 1000
接下来N行,每一行三个整数A,B,C
A表示大炮的威力
B表示大炮每次攻击消耗的火药量
C表示大炮每次攻击填充火药的时间
0<= A,B,C<= 100000

输出描述

输出在给定的时间结束之前或者火药存量耗尽之前给予城池的最大的打击。

解题思路

这是一道背包问题的变体,可以使用动态规划求解。

定义状态:dp[i][j] 表示前i种大炮在火药剩余量不超过j的情况下,最大的威力是多少。
状态转移方程如下:
dp[i][j] = max(dp[i-1][j], max(dp[i][j-c[i][1]*k]+c[i][0]*k)),其中k表示第i种大炮在火药剩余量不超过j的情况下最多能攻击的次数,c[i][0]表示第i个大炮的威力,c[i][1]表示第i个大炮每次攻击需消耗的火药量。
时间复杂度为 O(NMT),空间复杂度为 O(NMT),其中N,M,T分别表示大炮种类个数,火药总量和攻城总时间。

参考代码

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();
        int t = scanner.nextInt();

        int[][] c = new int[n + 1][3];
        for (int i = 1; i <= n; i++) {
            c[i][0] = scanner.nextInt(); // 威力
            c[i][1] = scanner.nextInt(); // 消耗火药量
            c[i][2] = scanner.nextInt(); // 填充时间
        }

        int[][] dp = new int[n + 1][m + 1];
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= m; j++) {
                int k = Math.min(j / c[i][1], t / c[i][2]); // 计算第i种大炮在火药剩余量不超过j的情况下最多能攻击的次数
                for (int l = 0; l <= k; l++) {
                    dp[i][j] = Math.max(dp[i][j], dp[i-1][j-l*c[i][1]]+l*c[i][0]); // 状态转移方程
                }
            }
        }

        System.out.println(dp[n][m]);
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值