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


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章