题目链接
题目描述
小红需要 种不同的魔法药剂。
她可以花 的价格购买第
种红色版本的魔法药剂。
她也可以用第 种和第
种红色版本的药剂来配置出第
种蓝色版本的药剂。
小红想知道,她最少需要花多少钱才能得到从 1 到 所有种类的魔法药剂(红色或蓝色均可)。
解题思路
这是一个典型的贪心问题,其核心在于每个决策都是独立的。
对于 到
的每一种魔法药剂
,我们都有两种获取它的方式:
- 直接购买红色版:成本为
。
- 配置蓝色版:成本为
,其中
和
是配置第
种药剂所需的两种红色药剂的编号。
关键在于,为某一种药剂做出选择(是购买还是配置)并不会影响到其他任何药剂的获取成本。所有红色药剂的原始价格 是固定不变的。
因此,我们可以对每一种药剂都独立地做出最优选择。对于第 种药剂,我们只需简单地比较直接购买和配置两种方式的成本,然后选择其中较小的一个即可。
第 种药剂的最小成本为
。
总的最小花费就是将这 种药剂的最小成本全部加起来。
总最小花费 。
实现上,我们先读入并存储所有红色药剂的价格。然后遍历每一种药剂,计算其最小获取成本,并累加到一个总和变量中。由于总花费可能很大,需要使用64位整型(long long
)来防止溢出。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
cin >> n;
vector<long long> c(n);
for (int i = 0; i < n; ++i) {
cin >> c[i];
}
long long total_cost = 0;
for (int i = 0; i < n; ++i) {
int u, v;
cin >> u >> v;
// 成本是 1-indexed,数组是 0-indexed
long long synthesis_cost = c[u - 1] + c[v - 1];
long long direct_cost = c[i];
total_cost += min(direct_cost, synthesis_cost);
}
cout << total_cost << endl;
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
long[] c = new long[n];
for (int i = 0; i < n; i++) {
c[i] = sc.nextLong();
}
long totalCost = 0;
for (int i = 0; i < n; i++) {
int u = sc.nextInt();
int v = sc.nextInt();
// 成本是 1-indexed,数组是 0-indexed
long synthesisCost = c[u - 1] + c[v - 1];
long directCost = c[i];
totalCost += Math.min(directCost, synthesisCost);
}
System.out.println(totalCost);
}
}
import sys
def solve():
try:
n_str = sys.stdin.readline()
if not n_str: return
n = int(n_str)
c = list(map(int, sys.stdin.readline().split()))
total_cost = 0
for i in range(n):
u, v = map(int, sys.stdin.readline().split())
# 成本是 1-indexed,数组是 0-indexed
synthesis_cost = c[u - 1] + c[v - 1]
direct_cost = c[i]
total_cost += min(direct_cost, synthesis_cost)
print(total_cost)
except (IOError, ValueError):
return
solve()
算法及复杂度
-
算法:贪心算法
-
时间复杂度:
。我们需要一次遍历来读取
个红色药剂的价格,另一次遍历来计算每种药剂的最小成本。
-
空间复杂度:
。我们需要一个大小为
的数组来存储所有红色药剂的价格。