zoj 3623 Battle Ships

题意:

一个游戏,敌人有L的血量,己方可以生产n种武器,每种武器的生产需要花费ti秒,这种武器产生之后的每一秒都可以对敌人的血量造成vi的伤害,并且每种武器的生产数量是没有限制的。

每一秒要么什么都不做,要么用来生产一种武器。

当敌人的血量为0时,己方获胜。

问最少需要多少时间使得己方获胜。

思路:

因为每种武器可以生产无数次,所以联想到完全背包。

如果计算前i秒造成的最大伤害,就会产生一个问题,一个武器生产之后会造成持续伤害,所以实际的状态不好表示。

换一个思路,把时间当作容量,那么就不必care前多少秒的状态了,只用关心在一个时间段内可以获得的最大伤害。

转移方程:

dp[j+t[i]] = max(dp[j+t[i]],dp[j]+j*v[i]).

对于这个方程的解释是,在j+t[i]这个时间段内,把前t[i]秒(从一开始)用来生产第i个武器,这个武器就在之后的j秒内产生作用,即为j*t[i],然后加上j这个时间段内产生的最大伤害。

找到第一个dp[i] >= L就是答案。

代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N = 1000;
 6 int dp[N];
 7 int t[N],v[N];
 8 int main()
 9 {
10     int n,l;
11     while (scanf("%d%d",&n,&l)!=EOF)
12     {
13         memset(dp,0,sizeof(dp));
14         for (int i = 0;i < n;i++)
15         {
16             scanf("%d%d",&t[i],&v[i]);
17         }
18         for (int i = 0;i < n;i++)
19         {
20             for (int j = 0;j < l*2;j++)
21             {
22                 dp[j+t[i]] = max(dp[j+t[i]],dp[j]+j*v[i]);
23             }
24         }
25         int ans = 0;
26         for (int i = 0;i < 1000;i++)
27         {
28             if (dp[i] >= l)
29             {
30                 ans = i;
31                 break;
32             }
33         }
34         //printf("%d
",dp[0]);
35         printf("%d
",ans);
36     }
37     return 0;    
38 }
原文地址:https://www.cnblogs.com/kickit/p/8823144.html