哈利喜欢玩角色扮演的电脑游戏《蜥蜴和地下室》。此时,他正在扮演一个魔术师。在最后一关,他必须和一排的弓箭手战斗。他唯一能消灭他们的办法是一个火球咒语。如果哈利用他的火球咒语攻击第i个弓箭手(他们从左到右标记),这个弓箭手会失去a点生命值。同时,这个咒语使与第i个弓箭手左右相邻的弓箭手(如果存在)分别失去b(1 ≤ b < a ≤ 10)点生命值。
因为两个端点的弓箭手(即标记为1和n的弓箭手)与你相隔较远,所以火球不能直接攻击他们。但是哈利能用他的火球攻击其他任何弓箭手。
每个弓箭手的生命值都已知。当一个弓箭手的生命值小于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
思路;先处理两端的弓箭手,因为题上说不能直接打到两端,然后直接dfs,
当x-1被杀死时,跳过开始x;
当x-1没有被杀死时,直接打爆,然后看杀死x-1的同时x是不是被杀死
具体看代码,代码中也有解释:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<math.h>
#include<map>
#include<vector>
#include<stack>
#include<iostream>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=25;
ll n,a,b;
ll h[N],ans;
void dfs(ll x,ll step)
{
if(x==n)
{
ans=min(ans,step);
return;
}
ll t=0,tt;
if(h[x-1]<0)
dfs(x+1,step);
if(h[x-1]>=0)
{
t=h[x-1]/b+1;
step+=t;
h[x-1]-=b*t;
h[x]-=a*t;
h[x+1]-=b*t;
dfs(x+1,step);
step-=t;
h[x-1]+=b*t;
h[x]+=a*t;
h[x+1]+=b*t;
}
tt=h[x]/a+1;
if(tt>t&&h[x]>=0)//如果x-1死亡但是x并没有死,有两种方法可以把x打爆
{ //一是直接打x,还有就是通过打x+1来打爆x
//所以用个for循环,枚举每打一次的状况
for(ll i=t+1;t<=tt;t++)
{
h[x-1]-=t*b;
h[x]-=t*a;
h[x+1]-=t*b;
step+=t;
dfs(x+1,step);
h[x-1]+=t*b;
h[x]+=t*a;
h[x+1]+=t*b;
step-=t;
}
}
return;
}
int main()
{
while(~scanf("%lld %lld %lld",&n,&a,&b))
{
ll i,j,d,res=0;
for(i=1;i<=n;i++)
scanf("%lld",&h[i]);
d=h[1]/b+1;//计算把第一个打爆所需要的火球数
h[1]-=d*b;
h[2]-=d*a;
h[3]-=d*b;
res+=d;
if(h[n]>=0)//可能打爆第一个的同时打爆了最后一个
{
d=h[n]/b+1;
h[n]-=d*b;
h[n-1]-=d*a;
h[n-2]-=d*b;
res+=d;
}
ans=inf;
dfs(2,0);
printf("%lld\n",res+ans);
}
return 0;
}