hdu 3008 Warcraft(基础dp题)

       这题我自己感觉是一道很经典的DP题目,对于DP大神来说是非常裸的题,但是对于我这样的DP初学者来说,我觉得是很好的一道入门题。。。收益匪浅。

 

      题意:以魔兽为背景,给定一个英雄,英雄要打倒一个boss,英雄初始的血量与魔法值都是100,boss的血量也是100,输入n,t,p;分别表示英雄有n个技能,在每一轮双方攻击完后可以恢复t的魔法值,boss的攻击力为p。

后来n行每行两个数ai,bi(大于0小于100),表示使用技能需要的魔法值与技能的伤害(必须至少有ai的魔法值才能发动相对应的技能)。英雄也有一个普通攻击,不需要魔法值,伤害为1;

      在每一回合中都是英雄先攻击。问最少用多少回合可以打倒boss,如在打倒boss之前英雄先死了就输出My god!


       解法:因为每次boss的伤害是固定的,所以英雄死的时间也是固定的,所以如果在那个时间内不能杀死boss,就My god了。因为这题是师兄出的DP基础题,所以一开始就认定用DP做了,建立的数组dp[i][j]意思是在i轮boss剩下j血量的情况下英雄最大的魔法值为dp[j];(我一开始错误的想法是第i轮boss被扣了j血量的情况下英雄的最大魔法值dp[j],可惜错了,不知道为什么,求大神解答。。。)这思路是看其他大神博客得出的。

       因为代码没有涉及到什么算法,主要是推出那个蛋疼的状态转移方程,所以就没有什么注释,也没有什么好说的。


       网上面的DP讲座都说,最重要是搞清楚问题的决策与状态,这样才能写出状态转移方程。

        所以小弟不才,就这题说说决策与状态(如果有错望各大神指出):

具体对照代码。。。

        状态:boss剩下j血量的状态;

              决策:是否使用第K个技能使状态变成:boss剩下j – skill[k].bi血量的状态。;(当然是在能使用这技能的情况下,前面有if判断)

而决策的判断条件就是魔法值了。因为在任何一个状态下,魔法值越多,就对英雄越有利。

所以态转移方程:dp[j – skill[k].bi] = max (dp[j – skill[k].bi],dp[j] – skill[k].ai + t);

 

 

 

#include <stdio.h>
#include <string.h>
typedef struct{
	int ai;
	int bi;
}node;
int max (int a,int b)
{
	return a > b ? a : b ;
}
int main ()
{
	node skill[110];
	int n,t,q,i,j,k,p;
	int dp[110];
	while (scanf ("%d%d%d",&n,&t,&q))
	{
		p = 0;
		if (n == 0 && t == 0 && q == 0)
			break;
		for (i = 1 ; i <= n ; i++)
			scanf ("%d%d",&skill[i].ai,&skill[i].bi);
		skill[0].ai = 0;
		skill[0].bi = 1;
		memset (dp,-1,sizeof(dp));
		dp[100] = 100;
		int time = (100 % q == 0) ? 100/q : 100 / q + 1 ;//英雄在time回合内要打到boss;
		for (i = 1 ; i <= time ; i ++)
		{
			for (j = 1 ; j <= 100 ; j ++)
			{
				if (dp[j] == -1)
					continue;
				for (k = 0 ; k <= n ; k ++)
				{
					if (j <= skill[k].bi && dp[j] >= skill[k].ai)
					{
						printf ("%d\n",i);
						p = 1;
						break;
					}
					else if (j > skill[k].bi && dp[j] >= skill[k].ai)
					{
						dp[j - skill[k].bi] = max (dp[j - skill[k].bi],dp[j] - skill[k].ai + t);
						if (dp[j + skill[k].bi] > 100)
							dp[j + skill[k].bi] = 100;
					}
				}
				if (p)
					break;
			}
			if(p)
				break;

		}
		if (!p)
			printf ("My god\n");	
	}
}

 

点赞