1. 程式人生 > >魔獸 DP

魔獸 DP

true logs 是你 scan craft ont span sin pri

【問題描述】
你玩過魔獸爭霸麽?不管你玩的好不好都不要緊!在玩遊戲的同時,我們有這樣的體驗。
遊戲中有很多英雄,但是你只能選擇其中之一。每個英雄都有自己的技能。當一個技能被使
用,它的代價是在花費英雄的一定的魔力值,也在同一時間傷害 boss。你在使用技能要根據
情報,應該在傷害敵人最大的時候的使用某些魔力技能。
現在我們送你去完成這樣一個任務殺死 boss。為了簡化這個問題:我們假設 boss 怪物
的生命值是 100,你的也是 100,你的魔力值也是 100 !你和 boss 輪流進行攻擊,並且你先手,
你每次攻擊 boss 耗時 1 秒。
每次你可以選擇使用普通攻擊(不花魔力),或一個特定的技能(條
件是你的現有魔力值不低於技能的花費成本(魔力值),天下沒有免費的午餐,所以你在支付


一定的魔力之後你才能使用這個技能!但我們是足夠好,為您提供一個魔力恢復指環(每秒鐘
可以恢復一些的魔力值),但是你不能擁有超過 100 魔力值上限 和 只要魔力沒有達到上限,
就總是在恢復。Boss 是 cruel,小心!
【輸入文件】
多組測試數據
每組數據的第一行輸入 3 個整數 n ,t ,q (0 < n < = 100,1 < = t < = 5,q> 0)
n:你自己的 n 種技能
t:魔力恢復指環每秒鐘可以幫助您恢復 t 點魔力值
q:boss 在你每次攻擊後對你 q 點傷害,不耗時。
緊接著 n 行,各有 2 整數 ai 和 bi(0 < ai,bi < = 100)。表示使用當前這個技能花費你 ai

魔力值,對 boss 的生命值的傷害點數 bi。
最後的一行是 n = t =q= 0。
【輸出文件】
每組測試數據輸出一行:
一個整數 min,殺死 boss 的最少時間,如果玩家死了,輸出“My god”(不含引號)。
【樣例輸入】
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
【樣例輸出】
4
My god
【提示】
當攻擊的時候,同一時間,你只能選擇一種攻擊模式,技能或者是普通攻擊,普通攻擊
只能傷害 boss 一點生命值。


很明顯的DP題,但是我考試的時候並沒有寫出,因為狀態定義的太差,導致轉移的時候有問題。

換了種狀態定義,就很好DP了:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

#define ll long long
#define il inline
#define db double

#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))

using namespace std;

int a[145];

int b[145];

int f[145][145];//j次攻擊,魔力為i時的最大傷害

il void work(int n,int t,int q)
{
	if(!n&&!t&&!q)
		exit(0);

	memset(f,0,sizeof(f));

	for(int i=1;i<=n;i++)
		scanf("%d%d",&a[i],&b[i]);

	a[0]=0,b[0]=1;
	for(int k=1;k<=100;k++)
		for(int i=0;i<=n;i++)
			for(int j=100;j>=a[i];j--)
				{
					int now=j-a[i]+t;
					if(now>100)
						now=100;
					f[now][k]=max(f[now][k],f[j][k-1]+b[i]);
					if(f[now][k]>=100&&(k-1)*q<=100)
						{
							printf("%d\n",k);
							return;
						}
				}
	
	printf("My god\n");
}

int main()
{
	freopen("warcraft.in","r",stdin);
	freopen("warcraft.out","w",stdout);

	int n,t,q;
	while(scanf("%d%d%d",&n,&t,&q)!=EOF)
		work(n,t,q);

	return 0;
}

魔獸 DP