zoj 3623 Battle Ships

来源:互联网 发布:淘宝回收手机被骗 编辑:程序博客网 时间:2024/05/17 23:20
思路: 完全背包
分析:
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;}



原创粉丝点击