(dfs) - 1489 蜥蜴和地下室

1489 蜥蜴和地下室

  1. 1 秒
  2.  
  3. 131,072 KB
  4.  
  5. 10 分
  6.  
  7. 2 级题

哈利喜欢玩角色扮演的电脑游戏《蜥蜴和地下室》。此时,他正在扮演一个魔术师。在最后一关,他必须和一排的弓箭手战斗。他唯一能消灭他们的办法是一个火球咒语。如果哈利用他的火球咒语攻击第i个弓箭手(他们从左到右标记),这个弓箭手会失去a点生命值。同时,这个咒语使与第i个弓箭手左右相邻的弓箭手(如果存在)分别失去b(1 ≤ b < a ≤ 10)点生命值。

因为两个端点的弓箭手(即标记为1和n的弓箭手)与你相隔较远,所以火球不能直接攻击他们。但是哈利能用他的火球攻击其他任何弓箭手。

每个弓箭手的生命值都已知。当一个弓箭手的生命值小于0时,这个弓箭手会死亡。请求出哈利杀死所有的敌人所需使用的最少的火球数。

如果弓箭手已经死亡,哈利仍旧可以将他的火球扔向这个弓箭手。


 收起

输入

第一行包含3个整数 n, a, b (3 ≤ n ≤ 10; 1 ≤ b < a ≤ 10),第二行包含n个整数——h1,h2,...,hn (1 ≤ hi ≤ 15), hi 是第i个弓箭手所拥有的生命力。

输出

以一行输出t——所需要的最少的火球数。

输入样例

3 2 1
2 2 2

输出样例

3

题解:由于 1 和 n 不能直接攻击,所以先直接攻击 2,n-1,将他们消灭,然后从 2 开始搜索到 n.

#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<bitset>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define eps (1e-8)
#define MAX 0x3f3f3f3f
#define u_max 1844674407370955161
#define l_max 9223372036854775807
#define i_max 2147483647
#define re register
#define pushup() tree[rt]=tree[rt<<1]+tree[rt<<1|1]
#define nth(k,n) nth_element(a,a+k,a+n);  // 将 第K大的放在k位
#define ko() for(int i=2;i<=n;i++) s=(s+k)%i // 约瑟夫
using namespace std;

inline int read(){
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' & c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}

typedef long long ll;
const double pi = atan(1.)*4.;
const int M=1e3+5;
const int N=1e6+5;
int h[M],n,a,b,ans=i_max;

void dfs(int x,int num){ //  x 指当前要直接攻击的编号  num 目前的攻击次数(2 - n)
    if(x==n){
        ans=min(ans,num);
        return ;
    }
    if(h[x-1]<0)          //  从当前位置移动到 下一个位置,充要条件是 h[x-1]<0
        dfs(x+1,num);
    int time1=0;
    if(h[x-1]>=0){        // 要将 x-1位置消灭,最少需要 攻打几次 x 位置的士兵
        time1=h[x-1]/b+1;
        h[x-1]-=time1*b;
        h[x]-=time1*a;
        h[x+1]-=time1*b;
        dfs(x+1,num+time1);
        h[x-1]+=time1*b;
        h[x]+=time1*a;
        h[x+1]+=time1*b;
    }
    int time2=h[x]/a+1;     //  time2 为将 x 位置的士兵消灭,需要 time2 次直接攻击
    if(h[x]>=0&&time2>time1){  //  要将 x-1 位置士兵消灭,只要攻打 x 位置士兵 [time1,time2]次,就可以了。
        for(int i=time1+1;i<=time2;i++){
            h[x-1]-=b*i;
            h[x]-=a*i;
            h[x+1]-=b*i;
            dfs(x+1,num+i);
            h[x-1]+=b*i;
            h[x]+=a*i;
            h[x+1]+=b*i;
        }
    }
    return ;
}
int main(){
    scanf("%d %d %d",&n,&a,&b);
    for(int i=1;i<=n;i++)
        scanf("%d",&h[i]);
    int sum=h[1]/b+1;     //  消灭 1 号
    h[1]-=sum*b;
    h[2]-=sum*a;
    h[3]-=sum*b;
    if(h[n]>=0){
        int sum1=h[n]/b+1;    //  消灭 n 号
        h[n]-=sum1*b;
        h[n-1]-=sum1*a;
        h[n-2]-=sum1*b;
        sum+=sum1;
    }
    dfs(2,0);
    printf("%d\n",ans+sum);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值