1 solutions
-
0
题目描述
塔子哥有多种火药枪和有限的火药量。每种火药枪的威力、消耗的火药量和填充时间各不相同。你需要帮助塔子哥在规定的时间内或在火药耗尽之前,给予敌人最大的伤害。
题目思路
1.理解问题:
每种火药枪的威力是固定的,每次开火消耗一定量的火药,并且在每次开火之前需要一定的填充时间。 不同种火药枪可以同时开火。
2.转换为多重背包问题:
每种火药枪可以看作一种物品,威力是价值,消耗的火药量是物品的体积,填充时间限制了每种火药枪的使用次数。 对于每种火药枪,可以发射的次数为 min(M // B[i], T // C[i]),这里 B[i] 是消耗的火药量,C[i] 是填充时间。
3.动态规划:
使用动态规划数组 dp,其中 dp[j] 表示使用 j 量火药所能达到的最大伤害。 通过迭代所有火药枪和可能的火药消耗量,更新最大伤害值。
代码说明
1.输入读取:
读取火药枪的种类数量 N,火药总量 M,以及攻城时间 T。 接下来,读取每种火药枪的威力、消耗的火药量和填充时间。
2.初始化变量:
创建一个数组 dp,大小为 M + 1,用来记录不同火药消耗下的最大伤害。
3.构建动态规划逻辑:
遍历每种火药枪,计算该火药枪能开火的最大次数。 使用倒序遍历更新 dp 数组,确保每种火药枪的使用次数不会重复。 输出结果:
最后,输出 dp 数组的最大值,即为在给定条件下能造成的最大伤害。
代码
Python代码
n, m, T = map(int, input().split()) A, B, C = [], [], [] for i in range(n): a, b, c = map(int, input().split()) A.append(a) B.append(b) C.append(c) dp = [0]*(m+1) # dp初始化为0 for i in range(n): # 枚举大炮 for j in range(m, -1, -1): # 倒序遍历使得一个大炮不能重复更新 mx = min((m-j)//B[i], T//C[i]) # 计算当前的大炮最多发射几下 for k in range(1, mx+1): # 枚举当前的第i门大炮发射几下 dp[j+k*B[i]] = max(dp[j+k*B[i]], dp[j]+k*A[i]) print(max(dp)) # 输出最大值
C++代码
#include <iostream> using namespace std; // 定义数组,存储火药枪的威力、消耗火药量和填充时间 int a[1005], b[1005], c[1005]; int dp[10004]; // 动态规划数组,存储不同火药消耗下的最大伤害 int main() { int n, m, T; // n: 火药枪种类数, m: 火药总量, T: 攻城时间 cin >> n >> m >> T; // 读取火药枪种类、火药总量和攻城时间 // 读取每种火药枪的威力、消耗火药量和填充时间 for (int i = 0; i < n; i++) cin >> a[i] >> b[i] >> c[i]; // 动态规划处理 for (int i = 0; i < n; i++) { // 遍历每种火药枪 for (int j = m; j >= 0; j--) { // 倒序遍历火药量 // 计算当前火药枪最多能发射的次数 int mx = min((m - j) / b[i], T / c[i]); for (int k = 1; k <= mx; k++) { // 遍历当前火药枪能发射的次数 // 更新动态规划数组,确保不超过总火药量 if (j + k * b[i] <= m) { dp[j + k * b[i]] = max(dp[j + k * b[i]], dp[j] + k * a[i]); // 更新最大伤害 } } } } // 找到最大伤害 int ans = 0; for (int i = 0; i <= m; i++) // 遍历所有可能的火药消耗量 ans = max(ans, dp[i]); // 更新最大伤害 cout << ans << endl; // 输出结果 return 0; // 程序结束 }
Java代码
import java.util.Scanner; 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[] a = new int[n]; // 威力 int[] b = new int[n]; // 消耗的火药量 int[] c = new int[n]; // 填充时间 // 读取每种火药枪的信息 for (int i = 0; i < n; i++) { a[i] = scanner.nextInt(); // 读取威力 b[i] = scanner.nextInt(); // 读取消耗的火药量 c[i] = scanner.nextInt(); // 读取填充时间 } // 初始化动态规划数组,大小为 m + 1 int[] dp = new int[m + 1]; // 动态规划处理 for (int i = 0; i < n; i++) { // 遍历每种火药枪 for (int j = m; j >= 0; j--) { // 倒序遍历剩余的火药量 // 计算当前火药枪最多能发射的次数 int mx = Math.min((m - j) / b[i], t / c[i]); // 遍历当前火药枪能发射的次数 for (int k = 1; k <= mx; k++) { // 更新动态规划数组,确保不超过总火药量 dp[j + k * b[i]] = Math.max(dp[j + k * b[i]], dp[j] + k * a[i]); } } } // 找到最大伤害 int ans = 0; // 初始化最大伤害为0 for (int i = 0; i <= m; i++) // 遍历所有可能的火药消耗量 ans = Math.max(ans, dp[i]); // 更新最大伤害 // 输出结果 System.out.println(ans); // 打印最大伤害 } }
Js代码
// 使输入流保持活动状态并设置编码 process.stdin.resume(); process.stdin.setEncoding('utf-8'); let input = ''; // 初始化输入字符串 // 监听输入数据事件,将数据追加到 input 字符串 process.stdin.on('data', (data) => { input += data; return; }); // 监听输入结束事件 process.stdin.on('end', () => { // 将输入数据按行分割 input = input.split('\n'); // 读取火药枪的种类数 n,火药总量 m 和攻城时间 t let n = Number(input[0].split(' ')[0]); let m = Number(input[0].split(' ')[1]); let t = Number(input[0].split(' ')[2]); // 初始化存储威力、消耗的火药量和填充时间的数组 let a = new Array(n).fill(0); // 威力数组 let b = new Array(n).fill(0); // 消耗的火药量数组 let c = new Array(n).fill(0); // 填充时间数组 let dp = new Array(m + 1).fill(0); // 动态规划数组,大小为 m + 1 // 读取每种火药枪的信息 for (let i = 0; i < n; i++) { a[i] = Number(input[i + 1].split(' ')[0]); // 读取威力 b[i] = Number(input[i + 1].split(' ')[1]); // 读取消耗的火药量 c[i] = Number(input[i + 1].split(' ')[2]); // 读取填充时间 } // 动态规划处理 for (let i = 0; i < n; i++) { // 遍历每种火药枪 for (let j = m; j >= 0; j--) { // 倒序遍历剩余的火药量 // 计算当前火药枪最多能发射的次数 let mx = Math.min(parseInt((m - j) / b[i]), parseInt(t / c[i])); // 遍历当前火药枪能发射的次数 for (let k = 1; k <= mx; k++) { // 更新动态规划数组,确保不超过总火药量 dp[j + k * b[i]] = Math.max(dp[j + k * b[i]], dp[j] + k * a[i]); } } } // 找到最大伤害 let ans = 0; // 初始化最大伤害为0 for (let i = 0; i <= m; i++) // 遍历所有可能的火药消耗量 ans = Math.max(ans, dp[i]); // 更新最大伤害 // 输出结果 console.log(ans); // 打印最大伤害 });
- 1
Information
- ID
- 15
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 7
- Tags
- # Submissions
- 85
- Accepted
- 19
- Uploaded By