题目描述:
在一款虚拟游戏中生活,你必须进行投资以增强在虚拟游戏中的资产以免被淘汰出局。现有一家Bank,它提供有若干理财产品 m 个,风险及投资回报不同,你有N(元)进行投资,能接收的总风险值为X。你要在可接受范围内选择最优的投资方式获得最大回报。
备注:
在虚拟游戏中,每项投资风险值相加为总风险值;
在虚拟游戏中,最多只能投资2个理财产品;
在虚拟游戏中,最小单位为整数,不能拆分为小数;
投资额*回报率 = 投资回报
输入描述:
第一行:
产品数(取值范围[1,20])
总投资额(整数,取值范国[1, 100001)
可接受的总风险 (整数,取值范围[1,200])
第二行:产品投资回报率Q序列,输入为整数,取值范国(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
JS参考解题:
解题思路:
可以通过动态规划来解决。我们可以定义一个三维数组 dp[i][j][k],表示投资前 i 个理财产品,总投资额不超过 j,总风险不超过 k 的情况下,能获得的最大回报。然后我们可以根据这个二维数组逆向推导出每个产品的投资额。
function maxReturn(products, totalInvestment, maxRisk, returns, risks, maxInvestments) {
const n = products; // 产品数
const m = totalInvestment; // 总投资额
const x = maxRisk; // 可接受的总风险
// 初始化 dp 数组
const dp = Array.from({ length: n + 1 }, () =>
Array.from({ length: m + 1 }, () => Array(x + 1).fill(0))
);
for (let i = 1; i <= n; i++) {
for (let j = 1; j <= m; j++) {
for (let k = 1; k <= x; k++) {
dp[i][j][k] = dp[i - 1][j][k]; // 不投资第 i 个产品的情况
if (risks[i - 1] <= k && maxInvestments[i - 1] <= j) { // 如果第 i 个产品的风险小于等于当前风险值,并且投资额小于等于总投资额
dp[i][j][k] = Math.max(dp[i][j][k], dp[i - 1][j - maxInvestments[i - 1]][k - risks[i - 1]] + returns[i - 1]); // 投资第 i 个产品的情况
}
}
}
}
// 根据 dp 数组逆向推导每个产品的投资额
let j = m;
let k = x;
const investments = Array(n).fill(0);
for (let i = n; i > 0 && j > 0 && k > 0; i--) {
if (dp[i][j][k] !== dp[i - 1][j][k]) { // 如果投资了第 i 个产品
investments[i - 1] = maxInvestments[i - 1]; // 投资额为最大投资额
j -= maxInvestments[i - 1]; // 减去投资的额度
k -= risks[i - 1]; // 减去投资的风险值
}
}
return investments.join(" ");
}
// 示例输入
const products = 5;
const totalInvestment = 100;
const maxRisk = 10;
const returns = [10, 20, 30, 40, 50];
const risks = [3, 4, 5, 6, 10];
const maxInvestments = [20, 30, 20, 40, 30];
// 输出
console.log(maxReturn(products, totalInvestment, maxRisk, returns, risks, maxInvestments));