蜥蜴和地下室 NOD 1489【dfs】

本文探讨了一款角色扮演游戏中的算法难题,玩家需使用最少次数的火球术击败一排弓箭手。文章详细解析了问题背景、输入输出要求,并分享了一段C++代码实现,通过深度优先搜索策略,巧妙地解决了这一复杂问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值