OD统一考试(C卷)
分值: 100分
题解: Java / Python / C++
题目描述
在一款虚拟游戏中生活,你必须进行投资以增强在虚拟游戏中的资产以免被淘汰出局。
现有一家Bank,它提供有若干理财产品m,风险及投资回报不同,你有N (元)进行投资,能接受的总风,险值为X。
你要在可接受范围内选择最优的投资方式获得最大回报。
说明:
-
在虚拟游戏中,每项投资风,险值相加为总风,险值;
-
在虚拟游戏中,最多只能投资2个理财产品;
-
在虚拟游戏中,最小单位为整数,不能拆分为小数;
-
投资额*回报率=投资回报
输入描述
第一行:产品数(取值范围[1, 20]),总投资额(整数,取值范围[1,10000]),可接受的总风险(整数,取值范围[1,200])
第二行:产品投资回报率序列,输入为整数,取值范围[1,60]
第三行:产品风险值序列,输入为整数,取值范围[1,100]
第四行:最大投资额度序列,输入为整数,取值范围[1,10000]
输出描述
每个产品的投资序列
示例1
输入:
5 100 10
10 20 30 40 50
3 4 5 6 10
20 30 20 40 30
输出:
0 30 0 40 0
说明:
投资第二项 30 个单位,第四项 40 个单位,总的投资风险为两项相加为 4+6=10。
题解
这道题是一个简单的贪心算法问题。下面是解题思路和代码的分析:
- 题目类型:贪心算法问题。
- 解题思路:通过贪心算法选择最优的投资方式,即在可接受范围内选择回报率高且风险低的投资方案。
- 代码描述:
- 读取输入数据:产品数、总投资额、可接受的总风险,产品投资回报率序列,产品风险值序列,最大投资额度序列。
- 初始化最大收益为0,创建一个空的字典
rs
用于存储最优投资数量。- 遍历产品,对于每个产品:
- 如果该产品的风险超过了可接受的总风险,则跳过该产品。
- 计算只投资该产品时的投资数量,更新最大收益和最优投资数量。
- 遍历剩余产品,计算两种产品组合的投资数量,更新最大收益和最优投资数量。
- 输出最优投资数量序列。
- 时间复杂度:假设产品数为m,则时间复杂度为O(m^2)。
- 空间复杂度:空间复杂度取决于存储最优投资数量的字典
rs
,最坏情况下为O(m)。
Java
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
/**
* @author code5bug
*/
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 产品数,总投资额,可接受的总风险
int m = in.nextInt(), n = in.nextInt(), x = in.nextInt();
in.nextLine(); // 忽略换行符
// 产品投资回报率序列
int[] reward = Arrays.stream(in.nextLine().split(" "))
.mapToInt(Integer::parseInt).toArray();
// 产品风险值序列
int[] risk = Arrays.stream(in.nextLine().split(" "))
.mapToInt(Integer::parseInt).toArray();
// 最大投资额度序列
int[] restrict = Arrays.stream(in.nextLine().split(" "))
.mapToInt(Integer::parseInt).toArray();
int maxReward = 0; // 最大收益
Map<Integer, Integer> rs = new HashMap<>();
for (int i = 0; i < m; i++) {
if (risk[i] > x) continue;
// 只购买 i 产品
int k = Math.min(restrict[i], n);
if (reward[i] * k > maxReward) {
rs.clear();
rs.put(i, k);
maxReward = reward[i] * k;
}
for (int j = i + 1; j < m; j++) {
if (risk[i] + risk[j] > x) continue;
int cnti = restrict[i], cntj = restrict[j];
if (reward[i] > reward[j]) {
cnti = Math.min(cnti, n);
cntj = Math.min(cntj, n - cnti);
} else {
cntj = Math.min(cntj, n);
cnti = Math.min(cnti, n - cntj);
}
if (reward[i] * cnti + reward[j] * cntj > maxReward) {
rs.clear();
rs.put(i, cnti);
rs.put(j, cntj);
maxReward = reward[i] * cnti + reward[j] * cntj;
}
}
}
StringBuilder builder = new StringBuilder();
for (int i = 0; i < m; i++) {
builder.append(rs.getOrDefault(i, 0)).append(" ");
}
System.out.println(builder.toString());
}
}
Python
# 导入必要的模块
from collections import defaultdict
# 获取输入数据
m, n, x = map(int, input().split())
reward = list(map(int, input().split()))
risk = list(map(int, input().split()))
restrict = list(map(int, input().split()))
max_reward = 0 # 最大收益
rs = defaultdict(int) # 存储最优方案
for i in range(m):
if risk[i] > x:
continue
# 只购买第 i 个产品
k = min(restrict[i], n)
if reward[i] * k > max_reward:
rs.clear()
rs[i] = k
max_reward = reward[i] * k
for j in range(i + 1, m):
if risk[i] + risk[j] > x:
continue
cnti, cntj = restrict[i], restrict[j]
if reward[i] > reward[j]:
cnti = min(cnti, n)
cntj = min(cntj, n - cnti)
else:
cntj = min(cntj, n)
cnti = min(cnti, n - cntj)
if reward[i] * cnti + reward[j] * cntj > max_reward:
rs.clear()
rs[i] = cnti
rs[j] = cntj
max_reward = reward[i] * cnti + reward[j] * cntj
# 输出最优方案
result = ' '.join(str(rs[i]) if i in rs else '0' for i in range(m))
print(result)
C++
#include <algorithm>
#include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;
int main()
{
int m, n, x;
cin >> m >> n >> x;
// 用于存储投资回报率、风险和产品投资限制的数组
vector<int> reward(m);
vector<int> risk(m);
vector<int> restrict(m);
// 读取投资回报率
for (int i = 0; i < m; i++) {
cin >> reward[i];
}
// 读取风险值
for (int i = 0; i < m; i++) {
cin >> risk[i];
}
// 读取投资限制
for (int i = 0; i < m; i++) {
cin >> restrict[i];
}
int maxReward = 0; // 最大收益
unordered_map<int, int> rs; // 存储最优投资数量的映射
for (int i = 0; i < m; i++) {
if (risk[i] > x) continue;
// 只投资于产品 i
int k = min(restrict[i], n);
if (reward[i] * k > maxReward) {
rs.clear();
rs[i] = k;
maxReward = reward[i] * k;
}
for (int j = i + 1; j < m; j++) {
if (risk[i] + risk[j] > x) continue;
int cnti = restrict[i], cntj = restrict[j];
if (reward[i] > reward[j]) { // i,j 谁回报率高优先投谁
cnti = min(cnti, n);
cntj = min(cntj, n - cnti);
} else {
cntj = min(cntj, n);
cnti = min(cnti, n - cntj);
}
if (reward[i] * cnti + reward[j] * cntj > maxReward) {
rs.clear();
rs[i] = cnti;
rs[j] = cntj;
maxReward = reward[i] * cnti + reward[j] * cntj;
}
}
}
// 输出每个产品的最优投资数量
for (int i = 0; i < m; i++) {
cout << rs[i] << " ";
}
cout << endl;
return 0;
}
❤️有考友通过专栏已经快速通过机考,都是原题哦~~ 💪
📝 订阅 http://t.csdnimg.cn/lifXk
🙏整理题解不易, 如果有帮助到您,请给点个赞 ❤️ 和收藏 ⭐,让更多的人看到。🙏🙏🙏