算法每一题,成长每一天~
C0E28 虚拟理财游戏
真题链接:【持续更新】2024华为 OD 机试E卷 机考真题库清单(全真题库)
思路
Java
import java.util.Scanner;
public class C0E28 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String[] split = in.nextLine().split(" ");
int n = Integer.parseInt(split[0]); // n个商品
int A = Integer.parseInt(split[1]); // 总投入
int R = Integer.parseInt(split[2]); // 总风险
// 录入回报率
int[] backs = new int[n];
String[] split1 = in.nextLine().split(" ");
for (int i = 0; i < n; i++) {
backs[i] = Integer.parseInt(split1[i]);
}
// 录入风险
int[] risks = new int[n];
String[] split2 = in.nextLine().split(" ");
for (int i = 0; i < n; i++) {
risks[i] = Integer.parseInt(split2[i]);
}
// 录入投入量
int[] amounts = new int[n];
String[] split3 = in.nextLine().split(" ");
for (int i = 0; i < n; i++) {
amounts[i] = Integer.parseInt(split3[i]);
}
// 投入单个产品,计算其回报
int[] singleBacks = new int[n];
calcSingleBack(backs, risks, amounts, singleBacks, n, A, R);
int maxBack = 0;
int maxIdx = 0, maxAmount = 0;
for (int i = 0; i < singleBacks.length; i++) {
if (singleBacks[i] > maxBack) {
maxBack = singleBacks[i];
maxIdx = i;
maxAmount = Math.min(A, amounts[i]);
}
}
// 投入两个产品,计算回报
int[] doubleBacks = new int[n * n / 2]; // 记录回报
int[][] records = new int[doubleBacks.length][4]; // 记录组合信息: 0-产品1, 1-产品1数量, 2-产品2, 3-产品2数量
calcDoubleBack(backs, risks, amounts, doubleBacks, records, n, A, R);
int maxBack2 = 0;
int maxIdx1 = 0, maxIdx2 = 0, maxAmount1 = 0, maxAmount2 = 0;
for (int i = 0; i < doubleBacks.length; i++) {
if (doubleBacks[i] > maxBack2) {
maxBack2 = doubleBacks[i];
maxIdx1 = records[i][0];
maxAmount1 = records[i][1];
maxIdx2 = records[i][2];
maxAmount2 = records[i][3];
}
}
// 输出
if (maxBack > maxBack2) {
for (int i = 0; i < n; i++) {
if (i == maxIdx) {
System.out.print(maxAmount);
} else {
System.out.print(0);
}
System.out.print(" ");
}
} else {
for (int i = 0; i < n; i++) {
if (i == maxIdx1) {
System.out.print(maxAmount1);
} else if (i == maxIdx2) {
System.out.print(maxAmount2);
} else {
System.out.print(0);
}
System.out.print(" ");
}
}
}
private static void calcSingleBack(int[] backs, int[] risks, int[] amounts, int[] singleBacks,
int n, int A, int R) {
for (int i = 0; i < n; i++) {
if (risks[i] <= R) {
int amount = Math.min(amounts[i], A); // 不能超过总投入
singleBacks[i] = amount * backs[i]; // 投入 x 回报率
}
}
}
private static void calcDoubleBack(int[] backs, int[] risks, int[] amounts,
int[] doubleBacks, int[][] records,
int n, int A, int R) {
int index = 0;
// 嵌套for循环, 遍历所有可能的组合
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
if (risks[i] + risks[j] <= R) {
// 全量投入高回报的,剩余投入低回报的
int highIdx = i, lowIdx = j;
if (backs[i] < backs[j]) {
int temp = highIdx;
highIdx = lowIdx;
lowIdx = temp;
}
int highAmount = Math.min(amounts[highIdx], A);
int lowAmount = Math.min(amounts[lowIdx], A - highAmount);
int back = highAmount * backs[highIdx] + lowAmount * backs[lowIdx];
doubleBacks[index] = back;
records[index][0] = highIdx;
records[index][1] = highAmount;
records[index][2] = lowIdx;
records[index][3] = lowAmount;
index++;
}
}
}
}
}
总结
1、没什么特别的,就是数学逻辑 比较多,需要耐心。
算法要多练多练多练!!