51nod 1489 蜥蜴和地下室 dfs

哈利喜欢玩角色扮演的电脑游戏《蜥蜴和地下室》。此时,他正在扮演一个魔术师。在最后一关,他必须和一排的弓箭手战斗。他唯一能消灭他们的办法是一个火球咒语。如果哈利用他的火球咒语攻击第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。

不过这地方需要注意一点,如果敌人只有三个,我们打死第一个的同时,很有可能最后一个也死了。

所以在打死最后一个时,先判断一下是否已经死了。

之后开始dfs,记录两个值,当前所在的位置和到达当前所在位置已经用了几次攻击了。

对于当前位置z,我们有两种选择,不打死留着靠下一个的溅射伤害打死,或者直接打死。

不过需要保证的是第z-1个必须死了。

①如果z-1位置的血量<0,那么我们可以直接dfs(下一个,ans) 注意是可以,不是一定 这个是z-1死了,直接进下一个

②看看第z-1个死了没,如果没死,计算利用溅射伤害打死第z-1个需要几下攻击,之后进入dfs(下一个,ans+下个) 这个是保证打死z-1,进下一个

③计算第z个被直接打死需要几下攻击。之后for(打死z-1到打死z),在这区间内的我们都可以执行。 dfs(下一个,ans+for) 这个是随意打,但需要保证z-1死了,z死没死无所谓。

全程需要注意一个问题,那就是如果前者早就死了,我们按照公式求会求出需要打负数次打死,我们要化为0.


#include<iostream>
#include<stdio.h>
#include<math.h>
#include<vector>
#include<queue>
using namespace std;
int INF=0x3f3f3f3f;
int H[15];
int ans1;
int ans2;
int n,a,b;
int ans;
void dfs(int dangqianweizhi,int cishu)
{
    if(dangqianweizhi==n)
    {
        ans2=min(ans2,cishu);
        return ;
    }
    if(H[dangqianweizhi-1]<0)//如果小于0,我们可以直接进入下一个,也不以不进
    {
        dfs(dangqianweizhi+1,cishu);
    }
    int ci1=H[dangqianweizhi-1]/b+1;;
    if(H[dangqianweizhi-1]>=0)//如果还有,我们可以把它直接打死为止,就进入下一个
    {
        
        H[dangqianweizhi-1]-=ci1*b;
        H[dangqianweizhi]-=ci1*a;
        H[dangqianweizhi+1]-=ci1*b;
        dfs(dangqianweizhi+1,cishu+ci1);
        H[dangqianweizhi-1]+=ci1*b;
        H[dangqianweizhi]+=ci1*a;
        H[dangqianweizhi+1]+=ci1*b;
    }
    if(ci1<0)
        ci1=0;
    int ci2=H[dangqianweizhi]/a+1;
    if(H[dangqianweizhi]>=0&&ci2>ci1)
    {


     for(int i=ci1;i<=ci2;i++)
     {
        H[dangqianweizhi-1]-=b*i;
        H[dangqianweizhi]-=a*i;
        H[dangqianweizhi+1]-=b*i;
        dfs(dangqianweizhi+1,cishu+i);
        H[dangqianweizhi-1]+=b*i;
        H[dangqianweizhi]+=a*i;
        H[dangqianweizhi+1]+=b*i;
     }
    }
    return ;


}
int main()
{
    cin>>n>>a>>b;
    for(int i=1;i<=n;i++)
    {
        cin>>H[i];
    }
    ans1=0;
    ans2=INF;
    int num=H[1]/b+1;
    H[1]-=num*b;
    H[2]-=num*a;
    H[3]-=num*b;
    ans1+=num;
    if(H[n]>=0)
    {
        num=H[n]/b+1;
        H[n]-=num*b;
        H[n-2]-=num*b;
        H[n-1]-=num*a;
        ans1+=num;
    }
    dfs(2,0);
    if(ans2==INF)
    {
        ans2=0;
    }
    cout<<ans1+ans2<<endl;


}














评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值