题目链接

小红的魔法药剂

题目描述

小红需要集齐 种魔法药剂(编号1到)。对于每种药剂,她只需要拥有红色或蓝色版本中的任意一种即可。

获取药剂的方式有两种:

  1. 直接购买:花费 金币购买第 种药剂的红色版本
  2. 调配合成:如果已经拥有第 种和第 种药剂的红色版本,就可以免费调配出第 种药剂的蓝色版本

给定每种红色药剂的价格以及每种蓝色药剂的合成配方,请计算集齐所有 种药剂的最小总金币数。

解题思路

这是一个典型的决策优化问题。我们需要为每一种药剂(从1到)决定如何获取它,以使得总花费最小。

核心思想:独立决策

关键的洞察在于,获取第 种药剂的决策,与其他药剂(如第 种)的最终获取方式是相互独立的。我们只需要为每一种药剂单独计算出其最低的获取成本,然后将所有这些最低成本相加,就是最终的答案。

分析每种药剂的最低成本

对于第 种药剂,我们有两种获取它的方式,需要比较它们的成本:

  1. 方式一:直接购买红色版本

    • 这种方式的成本是固定的,就是题目给出的价格
  2. 方式二:调配合成蓝色版本

    • 根据题目,合成蓝色版本的第 种药剂,需要拥有红色版本的原料药剂
    • 要拥有红色版本的原料,我们必须通过直接购买的方式获得它们。
    • 因此,通过合成方式获得第 种药剂的成本,就是购买其两种红色原料的成本之和:

最终决策

对于第 种药剂,其最低获取成本就是以上两种方式成本的较小值: min_cost_for_potion_i =

我们的总策略就是对每一种药剂都进行这样的计算,然后求和。

算法步骤

  1. 读取 以及所有 种红色药剂的价格
  2. 初始化一个总花费 total_cost 为0。
  3. 循环 次,在第 次循环中处理第 种药剂:
    • 读取合成第 种药剂所需的两种原料的编号
    • 获取直接购买的成本 direct_cost =
    • 计算合成的成本 synth_cost =
    • 找出这两种成本的较小值 min(direct_cost, synth_cost)
    • 将这个较小值累加到 total_cost 上。
  4. 循环结束后,total_cost 就是所需的最小总金币数。

代码

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;

    vector<long long> prices(n + 1);
    for (int i = 1; i <= n; ++i) {
        cin >> prices[i];
    }

    long long total_cost = 0;
    for (int i = 1; i <= n; ++i) {
        int u, v;
        cin >> u >> v;

        long long direct_cost = prices[i];
        long long synth_cost = prices[u] + prices[v];

        total_cost += min(direct_cost, synth_cost);
    }

    cout << total_cost << endl;

    return 0;
}
import java.util.Scanner;
import java.lang.Math;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();

        long[] prices = new long[n + 1];
        for (int i = 1; i <= n; i++) {
            prices[i] = sc.nextLong();
        }

        long totalCost = 0;
        for (int i = 1; i <= n; i++) {
            int u = sc.nextInt();
            int v = sc.nextInt();

            long directCost = prices[i];
            long synthCost = prices[u] + prices[v];

            totalCost += Math.min(directCost, synthCost);
        }

        System.out.println(totalCost);
    }
}
import sys

def solve():
    n = int(sys.stdin.readline())
    # 0-indexed prices, prices[i] is cost for potion i+1
    prices = list(map(int, sys.stdin.readline().split()))
    
    total_cost = 0
    for i in range(n):
        # Recipe for potion i+1
        u, v = map(int, sys.stdin.readline().split())
        
        # Direct purchase cost for potion i+1
        direct_cost = prices[i]
        
        # Synthesis cost needs red ingredients u and v
        # Potion u is at index u-1, potion v is at index v-1
        synth_cost = prices[u - 1] + prices[v - 1]
        
        total_cost += min(direct_cost, synth_cost)
        
    print(total_cost)

solve()

算法及复杂度

  • 算法:贪心
  • 时间复杂度:我们需要读取 个价格和 组配方,并在一个循环中处理它们。循环体内的操作是常数时间的。因此,总时间复杂度为
  • 空间复杂度:我们需要一个数组或列表来存储 种药剂的价格。因此,空间复杂度为