■ 题目描述
【攻城战】
一支攻城部队,有若干种大炮各座,以及数量有限的火药,每种大炮的威力不尽相同,且在每次开火之前都需要一定时间填充火药,
请你帮助指挥官在给定的时间结束之前或者火药存量耗尽之前给予城池最大的打击。
约束:
大炮每次开火的威力一样;
火药剩余量不小于大炮的消耗量,该大炮才能开火;
填充火药之外的时间忽略不计;
不同种大炮可以同时开火。
思路:背包问题,与01背包不同的是,关于dp[i][j]点的最优解,应该是Math.max(dp[i][j-b*k]+a*k)
其中k值最大为i大炮能够发射的最多次次数。
// 【攻城战】
// 一支攻城部队,有若干种大炮各座,以及数量有限的火药,每种大炮的威力不尽相同,且在每次开火之前都需要一定时间填充火药,
// 请你帮助指挥官在给定的时间结束之前或者火药存量耗尽之前给予城池最大的打击。
// 约束:
// 大炮每次开火的威力一样;
// 火药剩余量不小于大炮的消耗量,该大炮才能开火;
// 填充火药之外的时间忽略不计;
// 不同种大炮可以同时开火。
const readline = require('readline')
const r1 = readline.createInterface({
input:process.stdin,
output:process.stdout
})
let condition = null
let lines = []
r1.on('line',(line)=>{
let temp = line.split(' ').map(Number)
if(!condition){
condition =temp
}else{
lines.push(temp)
if(lines.length===condition[0]){
r1.close()
}
}
})
r1.on('close',()=>{
getMax(condition,lines)
})
function getMax(condition,lines){
let [types,amount,time]=condition
let dp = lines.map(()=>{return new Array(amount+1).fill(0)})
for(let i = 0;i<amount+1;i++){
// k为攻击的最多次数
let k1 = parseInt(i/lines[0][1])>=0?parseInt(i/lines[0][1]):0
let k2 = parseInt(time/lines[0][2])>=0?parseInt(time/lines[0][2]):0
let k = Math.min(k1,k2)
dp[0][i]=k*lines[0][0]
}
for(let i = 1;i<dp.length;i++){
for(let j = 1;j<amount+1;j++){
let k1 = parseInt(j/lines[i][1])>=0?parseInt(j/lines[i][1]):0
let k2 = parseInt(time/lines[i][2])>=0?parseInt(time/lines[i][2]):0
let k = Math.min(k1,k2)
let temp = []
for(let a=0;a<=k;a++){
if((j-lines[i][1]*a)>=0){
temp.push(dp[i-1][j-lines[i][1]*a]+lines[i][0]*a)
}else{
temp.push(lines[i][0]*a)
}
}
dp[i][j]=Math.max(...temp)
}
}
console.log(dp)
console.log(dp[dp.length-1][dp[0].length-1])
}