题意:
一个游戏,敌人有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\n",dp[0]); 35 printf("%d\n",ans); 36 } 37 return 0; 38 }