51nod 1489(不懂) dfs(暴搜)也可dp

题目:

搜索 CodeForces
1489 蜥蜴和地下室
1 秒 131,072 KB 10 分 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


code is from https://www.cnblogs.com/geloutingyu/p/6298396.html


#pragma comment(linker, "/STACK:10240000,10240000")
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <cstdlib>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
const double pi = acos(-1.0);
const int N=1e3+10;
const int mod = 1e9 + 7;
#define inf 0x3f3f3f3f

int gg[50],ans=inf, n, a, b;
void dfs(int pos,int num)
{
    int cnt=0,cc=0;
    if(pos == n) //*** 到达第n个人时返回并更新攻击次数
    {
        ans = min(ans, num);
        return ;
    }
    if(gg[pos-1]<0) //*** 只有前一个人死了之后才能向后移动
    {
        dfs(pos+1,num);
    }
    if(gg[pos-1]>=0)//***只处理大于等于零的情况
    {
        cnt=gg[pos-1]/b+1;
        gg[pos-1]-= b*cnt;
        gg[pos] -=a*cnt;
        gg[pos+1]-=b*cnt;
        dfs(pos+1,num+cnt);
        gg[pos-1]+=b*cnt;//*** 注意回溯时要将前面改变的量复原
        gg[pos]+=a*cnt;
        gg[pos+1]+=b*cnt;
    }
    cc= gg[pos]/a+1;
    if(cc>cnt && gg[pos]>=0)//*** 如果此时pos-1已死,而pos还活着,我们可
        //以选择直接将其杀死再移向下一个或者直接移向下一位
        //当消灭pos-1位置的次数可以在cnt和cc之间时,暴搜找到最合适的次数
    {
        for(int i=cnt+1;i<=cc;i++)
        {
            gg[pos-1]-=b*i;
            gg[pos]-=a*i;
            gg[pos+1]-=b*i;
            dfs(pos+1,num+i);
            gg[pos-1]+=b*i;
            gg[pos]+=a*i;
            gg[pos+1]+=b*i;
        }
    }
    return ;
}
int main()
{
    int num=0;
    cin >> n >> a >>b;
    for(int i=1;i<=n;i++)
    {
        cin>>gg[i];
    }
    int cnt=gg[1]/b+1;
    num+=cnt;
    gg[1]-=b*cnt;
    gg[2]-=a*cnt;
    gg[3]-=b*cnt;
    if(gg[n]>=0)
    {
        cnt = gg[n]/b+1;        
        num+=cnt;
        gg[n-2]-=b*cnt;
        gg[n-1]-=a*cnt;
        gg[n]-=b*cnt;
    }
    dfs(2,0);
    if(ans == inf)
    {
        ans = 0;
    }
    cout << ans+num <<endl;
    
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值