Warcraft
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1381 Accepted Submission(s): 727
Problem Description
Have you ever played the Warcraft?It doesn't matter whether you have played it !We will give you such an experience.There are so many Heroes in it,but you could only choose one of them.Each Hero has his own skills.When such a Skill is used ,it costs some MagicValue,but hurts the Boss at the same time.Using the skills needs intellegence,one should hurt the enemy to the most when using certain MagicValue.
Now we send you to complete such a duty to kill the Boss(So cool~~).To simplify the problem:you can assume the LifeValue of the monster is 100, your LifeValue is 100,but you have also a 100 MagicValue!You can choose to use the ordinary Attack(which doesn't cost MagicValue),or a certain skill(in condition that you own this skill and the MagicValue you have at that time is no less than the skill costs),there is no free lunch so that you should pay certain MagicValue after you use one skill!But we are good enough to offer you a "ResumingCirclet"(with which you can resume the MagicValue each seconds),But you can't own more than 100 MagicValue and resuming MagicValue is always after you attack.The Boss is cruel , be careful!
Now we send you to complete such a duty to kill the Boss(So cool~~).To simplify the problem:you can assume the LifeValue of the monster is 100, your LifeValue is 100,but you have also a 100 MagicValue!You can choose to use the ordinary Attack(which doesn't cost MagicValue),or a certain skill(in condition that you own this skill and the MagicValue you have at that time is no less than the skill costs),there is no free lunch so that you should pay certain MagicValue after you use one skill!But we are good enough to offer you a "ResumingCirclet"(with which you can resume the MagicValue each seconds),But you can't own more than 100 MagicValue and resuming MagicValue is always after you attack.The Boss is cruel , be careful!
Input
There are several test cases,intergers n ,t and q (0<n<=100,1<=t<=5,q>0) in the first line which mean you own n kinds of skills ,and the "ResumingCirclet" helps you resume t points of MagicValue per second and q is of course the hurt points of LifeValue the Boss attack you each time(we assume when fighting in a second the attack you show is before the Boss).Then n lines follow,each has 2 intergers ai and bi(0<ai,bi<=100).which means using i skill costs you ai MagicValue and costs the Boss bi LifeValue.The last case is n=t=q=0.
Output
Output an interger min (the minimun time you need to kill the Boss)in one line .But if you die(the LifeValue is no more than 0) ,output "My god"!
Sample Input
4 2 25 10 5 20 10 30 28 76 70 4 2 25 10 5 20 10 30 28 77 70 0 0 0
Sample Output
4 My godHintHint: When fighting,you can only choose one kind of skill or just to use the ordinary attack in the whole second,the ordinary attack costs the Boss 1 points of LifeValue,the Boss can only use ordinary attack which costs a whole second at a time.Good Luck To You!
Source
09年哈工程出的多校DP题。在DP处理的基础上增加了回蓝的机制,更有利于理解无后效性(后期如果需要此状态,无需知道此状态如何求得,只需要利用此状态的暂时的最优解即可)。记录dp[i][j]为第i秒剩j蓝所能对BOSS已造成的最大伤害,则DP方程为:dp[i][j]=max(dp[i][j],dp[i-1][j+skill[k].a]+skill[b])。本题除了技能还有普攻,而普攻可以看成0耗蓝,1输出的技能,所以这个问题可以完美解决。主角的存活时间是固定的,所以可以预先求出,作为DP外层的控制。难点是由于回蓝机制每个时间点过后对于dp值的更新,这里还需要分类讨论,因为蓝不能超过100,所以如果一次性回蓝会超过100需要另外讨论,只需要直接更新即可(后期的使用总是希望蓝更多,可以分类讨论思考:前者高,被更新;后者高,后者总是比前者更优),这里可以深刻理解无后效性这个特性。
/*------------------Header Files------------------*/
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <ctype.h>
#include <cmath>
#include <stack>
#include <queue>
#include <map>
#include <vector>
#include <limits.h>
using namespace std;
/*------------------Definitions-------------------*/
#define LL long long
#define PI acos(-1.0)
#define INF 0x3F3F3F3F
#define MOD 10E9+7
#define MAX 500050
/*---------------------Work-----------------------*/
int dp[150][150];
struct node
{
int a,b;
}skill[150];
bool cmp(node s,node t)
{
return s.a<t.a;
}
void work()
{
int n,t,q;
while(scanf("%d%d%d",&n,&t,&q))
{
if(n==0&&t==0&&q==0) break;
for(int i=1;i<=n;i++)
scanf("%d%d",&skill[i].a,&skill[i].b);
sort(skill+1,skill+n+1,cmp);
skill[0].a=0,skill[0].b=1; //普攻
//计算存活时间,是一固定值
int survive;
if(100%q==0) survive=100/q;
else survive=100/q+1;
//DP算法
memset(dp,0,sizeof(dp));
for(int i=1;i<=survive;i++)
{
for(int j=0;j<=100;j++)
{
int Max=0;
for(int k=0;k<=n;k++)
{
if(skill[k].a+j>100) break;
Max=max(Max,dp[i-1][j+skill[k].a]+skill[k].b);
}
dp[i][j]=Max;
}
//处理回蓝问题(打完才回蓝)
//注意这里只需要更新即可(无后效性)
for(int j=99;j>100-t;j--) //蓝会回到100的情况
dp[i][100]=max(dp[i][j],dp[i][100]);
for(int j=100-t;j>=0;j--) //普通的回蓝情况
dp[i][j+t]=max(dp[i][j],dp[i][j+t]);
}
int i,j;
for(i=1;i<=survive;i++)
{
for(j=0;j<=100;j++)
if(dp[i][j]>=100) break;
if(j<=100)
{
printf("%d\n",i);
break;
}
}
if(i>survive) printf("My god\n");
}
}
/*------------------Main Function------------------*/
int main()
{
//freopen("test.txt","r",stdin);
//freopen("cowtour.out","w",stdout);
//freopen("cowtour.in","r",stdin);
work();
return 0;
}