思路: 完全背包
分析:
1 有n种战舰和敌人的总的血量L,每一种战舰的创建时间为ti,每秒钟对敌人的伤害的血量为li
2 当敌人的血量为0的时候玩家赢了,求玩家最少的时间赢了游戏
3 这边如果我们用血量去做背包dp[j]表示伤害血量为j的最小时间的话,状态转移方程无法推出,那么我们考虑用时间去做背包dp[j]表示时间为j的最大伤害血量,那么我们从小到达枚举时间k,只要找到一个dp[k] >= L,说明玩家赢了
4 很容易写出状态转移方程k表示时间为k,dp[k] = max(dp[k] , dp[k-[ti]+(k-t[i])*l[i]);很好理解如果不创建第i个战舰就是dp[k],再创建第i个就是dp[k-t[i]]+(k-t[i])*l[i])为什么是这样的呢?因为总的时间为k那么攻击的时间为k-t[i],所以伤害的血量为(k-t[i])*l[i]
分析:
1 有n种战舰和敌人的总的血量L,每一种战舰的创建时间为ti,每秒钟对敌人的伤害的血量为li
2 当敌人的血量为0的时候玩家赢了,求玩家最少的时间赢了游戏
3 这边如果我们用血量去做背包dp[j]表示伤害血量为j的最小时间的话,状态转移方程无法推出,那么我们考虑用时间去做背包dp[j]表示时间为j的最大伤害血量,那么我们从小到达枚举时间k,只要找到一个dp[k] >= L,说明玩家赢了
4 很容易写出状态转移方程k表示时间为k,dp[k] = max(dp[k] , dp[k-[ti]+(k-t[i])*l[i]);很好理解如果不创建第i个战舰就是dp[k],再创建第i个就是dp[k-t[i]]+(k-t[i])*l[i])为什么是这样的呢?因为总的时间为k那么攻击的时间为k-t[i],所以伤害的血量为(k-t[i])*l[i]
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int MAXN = 610; int n , sum; int t[MAXN] , l[MAXN]; int dp[MAXN]; int solve(){ for(int k = 1 ; k <= 600 ; k++){ memset(dp , 0 , sizeof(dp)); for(int i = 1 ; i <= n ; i++){ for(int j = t[i] ; j <= k ; j++) dp[j] = max(dp[j] , dp[j-t[i]]+(j-t[i])*l[i]); if(dp[k] >= sum) return k; } } } int main(){ while(scanf("%d%d" , &n , &sum) != EOF){ for(int i = 1 ; i <= n ; i++) scanf("%d%d" , &t[i] , &l[i]); printf("%d\n" , solve()); } return 0; }