您的位置:首页 > 其它

zoj 3623 Battle Ships

2013-07-06 22:34 393 查看
思路: 完全背包

分析:

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;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: