zoukankan      html  css  js  c++  java
  • CodeForces

    Lizards and Basements 2

    题目大意:

    有一队人,你可以用火球点某个人,会对当前人造成(a)点伤害,对旁边的人造成(b)点伤害。

    不能打(1)号和(n)号,求最少多少发点死所有人。

    输出最少次数和每次选择攻击的人的序列。

    思路:

    看数据范围容易想到暴力(dfs),由于(1)号点不能打,我们考虑从(2)号点开始(dfs),直到(n-1)号点。

    (dfs(x, sum))为前(x)个敌人至少需要攻击(sum)次。

    注意判断是否能打掉最左边和最右边的敌人。

    Code:
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 15;
    const int INF = 0x3f3f3f3f;
    
    int h[N], n, a, b, ans = INF;
    vector<int> tmp, seq;
    
    void dfs(int x, int sum) { //dfs(x, sum)表示打掉前x个弓箭手最少需要打sum发
        if (sum >= ans) return; //最优性剪枝
        if (x == n) { //搜索结束
            if (h[n] < 0) { //如果能把最右边的打掉则可更新答案
                ans = sum;
                seq = tmp;
            }
            return;
        }
        for (int i = 0; i <= max({h[x - 1] / b, h[x] / a, h[x + 1] / b}) + 1; i++) { //枚举攻击次数
            if (h[x - 1] - b * i < 0) { //如果能打掉最左边
                h[x - 1] -= b * i;
                h[x] -= a * i;
                h[x + 1] -= b * i;
                for (int j = 0; j < i; j++) { //按攻击次数加入到被攻击敌人序列中
                    tmp.push_back(x);
                }
                dfs(x + 1, sum + i); //继续往后搜
                h[x - 1] += b * i; //回溯
                h[x] += a * i;
                h[x + 1] += b * i;
                for (int j = 0; j < i; j++) { //从序列中弹出
                    tmp.pop_back();
                }
            }
        }
    }
    
    int main() {
        cin >> n >> a >> b;
        for (int i = 1;i <= n; i++) cin >> h[i];
        dfs(2, 0);
        cout << ans << endl;
        for (auto i : seq) cout << i << " ";
        cout << endl;
        return 0;
    }
    
  • 相关阅读:
    二维空间轨迹聚类
    Java 格式化输出
    Linux 小笔记
    Nginx ServerName 配置说明(转)
    LVS
    Nginx + tomcat 实现简单集群(基于反向代理方式)
    mysql 外键
    tomcat 日志输出
    tomcat https
    SpringMVC表单标签简介
  • 原文地址:https://www.cnblogs.com/Nepenthe8/p/13692561.html
Copyright © 2011-2022 走看看