1. 程式人生 > >51Nod-1489 蜥蜴和地下室(暴力DFS)

51Nod-1489 蜥蜴和地下室(暴力DFS)



哈利喜歡玩角色扮演的電腦遊戲《蜥蜴和地下室》。此時,他正在扮演一個魔術師。在最後一關,他必須和一排的弓箭手戰鬥。他唯一能消滅他們的辦法是一個火球咒語。如果哈利用他的火球咒語攻擊第i個弓箭手(他們從左到右標記),這個弓箭手會失去a點生命值。同時,這個咒語使與第i個弓箭手左右相鄰的弓箭手(如果存在)分別失去b(1 ≤ b < a ≤ 10)點生命值。

因為兩個端點的弓箭手(即標記為1n的弓箭手)與你相隔較遠,所以火球不能直接攻擊他們。但是哈利能用他的火球攻擊其他任何弓箭手。

每個弓箭手的生命值都已知。當一個弓箭手的生命值小於0時,這個弓箭手會死亡。請求出哈利殺死所有的敵人所需使用的最少的火球數。

如果弓箭手已經死亡,哈利仍舊可以將他的火球扔向這個弓箭手。


Input
第一行包含3個整數 n, a, b (3 ≤ n ≤ 10; 1 ≤ b < a ≤ 10),第二行包含n個整數——h1,h2,...,hn (1 ≤ hi ≤ 15), hi 是第i個弓箭手所擁有的生命力。
Output
以一行輸出t——所需要的最少的火球數。
Input示例
3 2 1
2 2 2
Output示例
3
思路:每次從第一個血量大於等於0的弓箭手開始,在dfs之前先把頭和尾打爆,並且儘量不直接打爆 ,只有這樣才能保證用的火球術最少,剩下直接dfs了。N很小,所以可以無腦暴力, 程式碼裡的註釋寫的很清楚,所以這裡不再過多解釋。。(網上有DP解法,只怪我太弱,不會用)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<limits.h>
#include<queue>
#include<stack>
#include<vector>
#include<math.h>
#include<map>
using namespace std;
#define maxn 105
#define inf 0xfffffff  
typedef long long ll;
ll s[maxn],n,a,b,ans=inf,sum;
void dfs(ll x,ll num)//x表示當前弓箭手,num表示當前釋放火球術的次數 
{
	if(x==n)
	{
	 ans=min(ans,num);
	 return;
    }
	if(s[x-1]<0)
	dfs(x+1,num);
	ll t=0;
	if(s[x-1]>=0)
	{
	t=s[x-1]/b+1;
	num+=t;
	s[x-1]-=t*b;
	s[x]-=t*a;
	s[x+1]-=t*b;
	dfs(x+1,num);
	num-=t;
	s[x-1]+=t*b;
	s[x]+=t*a;
	s[x+1]+=t*b;
    }
	ll t1=s[x]/a+1;
	if(s[x]>=0 && t1>t)//假如打爆x-1後x還活著,則說明x的血量大於x-1,
	//因此要打爆x,此時打爆x有兩種方法,就是直接打爆和通過
	//打爆x+1來打爆x 
	{
		for(int i=t+1;i<=t1;i++)
		{
			num+=i;
			s[x-1]-=i*b;
			s[x]-=i*a;
			s[x+1]-=i*b;
			dfs(x+1,num);
			num-=i;
			s[x-1]+=i*b;
			s[x]+=i*a;
			s[x+1]+=i*b;
		 } 
	}
	return ;
}
int  main()
{
	ll i,j;
	memset(s,0,sizeof(s));
	scanf("%lld%lld%lld",&n,&a,&b);
	for(i=1;i<=n;i++)
	scanf("%lld",&s[i]);
	ll x=s[1]/b+1;//先把頭和尾打爆 
	sum+=x;
	s[1]-=x*b;
	s[2]-=x*a;
	s[3]-=x*b;
	if(s[n]>=0)
	{
	   x=s[n]/b+1;
	   sum+=x;
	   s[n]-=x*b;
	   s[n-1]-=x*a;
	   s[n-2]-=x*b;
	}
	dfs(2,0); 
	if(ans==inf)ans=0;
	printf("%lld\n",sum+ans);
}