题解:学而思编程 最小消耗

【题目来源】

学而思编程:最小消耗

【题目描述】

\(n\) 个怪兽等待你去消灭。

怪兽共分为两种形态,不妨用 \(0\)\(1\) 来表示。

消灭一个 \(0\) 形态的怪兽需要耗费的法力值为 \(a\)

消灭一个 \(1\) 形态的怪兽需要耗费的法力值为 \(b\)

你还可以使用改造魔法将 \(0\) 形态怪兽改造为 \(1\) 形态或将 \(1\) 形态怪兽改造为 \(0\) 形态。

改造一个怪兽需要耗费的法力值为 \(c\)

请问,将怪兽全部消灭最少需要耗费多少法力值。

【输入】

第一行包含整数 \(T\),表示共有 \(T\) 组测试数据。

每组数据第一行包含四个整数 \(n,a,b,c\)

第二行包含一个长度为 \(n\)\(01\) 字符串,其中的第 \(i\) 个字符表示第 \(i\) 个怪兽的初始形态。

【输出】

每组数据结果占一行,输出一个整数表示最小消耗

【输入样例】

3
4 1 2 1
1001
6 1 1 1
101011
3 2 1 3
111

【输出样例】

6
6
3

【核心思想】

  1. 问题分析:给定 \(n\) 个怪兽,每个怪兽有形态 \(0\)\(1\)。消灭形态 \(0\) 消耗 \(a\),消灭形态 \(1\) 消耗 \(b\),改造一个怪兽消耗 \(c\)。求消灭所有怪兽的最小总消耗。这是一个贪心决策问题,关键在于对每个怪兽独立决策:直接消灭还是改造后再消灭。

  2. 算法选择

    • 独立贪心:每个怪兽的处理方式相互独立,分别计算两种形态的最优处理成本
    • 最小值选择:对于每个怪兽,比较"直接消灭"和"改造后消灭"两种方案,取较小值
  3. 关键步骤

    • 初始化:读取 \(T\)(测试组数)
    • 处理每组数据
      • 读取 \(n, a, b, c\) 和形态字符串 \(s\)
      • 计算单怪兽最优成本
        • kill0 = min(a, b + c):形态 \(0\) 的怪兽,直接消灭(成本 \(a\))或改造成 \(1\) 再消灭(成本 \(b + c\)),取较小值
        • kill1 = min(b, a + c):形态 \(1\) 的怪兽,直接消灭(成本 \(b\))或改造成 \(0\) 再消灭(成本 \(a + c\)),取较小值
      • 累加总成本
        • ans = 0
        • 遍历 \(i\)\(0\)\(n-1\)
          • s[i] == '0'ans += kill0
          • 否则:ans += kill1
      • 输出 ans
  4. 时间/空间复杂度

    • 时间复杂度:\(O(T \times n)\),每组数据线性遍历字符串
    • 空间复杂度:\(O(n)\),存储形态字符串
  5. 独立贪心决策的核心思想

    • 怪兽间独立性:每个怪兽的改造和消灭决策不影响其他怪兽,总成本为各怪兽成本之和,无耦合约束
    • 单怪兽最优即全局最优:由于无跨怪兽约束,每个怪兽取自身最小成本即可保证全局最小
    • 两种策略对比:对每个怪兽只有两种选择(直接消灭当前形态 / 改造成另一形态再消灭),\(min\) 操作覆盖所有可能
    • 改造的双向性\(0 \to 1\)\(1 \to 0\) 的改造成本相同(均为 \(c\)),但改造后的消灭成本不同,需分别计算
    • 适用于"独立个体 + 二元选择"类问题,贪心策略将组合优化简化为每个元素的独立决策

【算法标签】

模拟

【代码详解】

#include <bits/stdc++.h>
using namespace std;
int T;
string s;
int main()
{
    cin >> T;  // 读取测试用例数量

    while (T--)  // 处理每个测试用例
    {
        int n, a, b, c;
        cin >> n >> a >> b >> c >> s;  // 读取n, a, b, c和字符串s

        int kill0 = min(a, b + c);  // 处理字符'0'的最小花费
        int kill1 = min(b, a + c);  // 处理字符'1'的最小花费

        int ans = 0;  // 总花费

        for (int i = 0; i <= n - 1; i++)  // 遍历字符串s
        {
            if (s[i] == '0')  // 如果字符是'0'
            {
                ans += kill0;  // 加上处理'0'的最小花费
            }
            else  // 如果字符是'1'
            {
                ans += kill1;  // 加上处理'1'的最小花费
            }
        }

        cout << ans << endl;  // 输出总花费
    }

    return 0;
}

【运行结果】

3
4 1 2 1
1001
6
6 1 1 1
101011
6
3 2 1 3
111
3
posted @ 2026-07-04 15:05  团爸讲算法  阅读(9)  评论(0)    收藏  举报