#P3031. 虚拟理财游戏(100分)
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 252
            Accepted: 55
            Difficulty: 2
            
          
          
          
                       所属公司 : 
                              华为od
                                
            
                      
          
 
- 
                        算法标签>暴力枚举          
 
虚拟理财游戏(100分)
思路:枚举
一开始看题目还以为是一道二维背包DP,但是题目加了一个限制条件:最多只能投资两个理财产品,那么要么就是投资一个,要么就是投资两个,就分别枚举这两种情况,更新最大回报即可。
Python 代码
from itertools import combinations
def main():
    # 读取第一行输入:产品数 m,总投资 N,可接受风险 X
    m, N, X = map(int, input().split())
    
    # 读取第二行输入:各产品的回报率
    return_rates = list(map(int, input().split()))
    
    # 读取第三行输入:各产品的风险值
    risk_values = list(map(int, input().split()))
    
    # 读取第四行输入:各产品的最大投资额度
    max_investments = list(map(int, input().split()))
    
    # 初始化最大回报值和最佳投资分配方案
    max_return = 0
    best_allocation = [0]*m
    
    # 枚举所有可能的1个和2个产品组合
    for r in range(1,3):
        for combo in combinations(range(m), r):
            # 计算当前组合的总风险值
            total_risk = sum(risk_values[i] for i in combo)
            if total_risk > X:
                continue  # 超出可接受风险,跳过此组合
            
            remaining = N  # 剩余的投资额度
            allocation = [0]*m  # 当前组合的投资分配
            # 按回报率降序排序组合中的产品,优先投资回报率高的产品
            sorted_combo = sorted(combo, key=lambda x: return_rates[x], reverse=True)
            total = 0  # 当前组合的总回报
            
            for i in sorted_combo:
                invest = min(max_investments[i], remaining)  # 可投资的最大额度
                allocation[i] = invest
                total += invest * return_rates[i]  # 计算回报
                remaining -= invest  # 更新剩余投资额度
            
            # 更新最大回报和最佳投资分配方案
            if total > max_return:
                max_return = total
                best_allocation = allocation.copy()
    
    # 输出最佳投资分配方案
    print(' '.join(map(str, best_allocation)))
if __name__ == "__main__":
    main()
Java 代码
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 读取第一行输入:产品数 m,总投资 N,可接受风险 X
        int m = scanner.nextInt();
        int N = scanner.nextInt();
        int X = scanner.nextInt();
        
        // 读取第二行输入:各产品的回报率
        int[] returnRates = new int[m];
        for(int i = 0; i < m; i++) {
            returnRates[i] = scanner.nextInt();
        }
        
        // 读取第三行输入:各产品的风险值
        int[] riskValues = new int[m];
        for(int i = 0; i < m; i++) {
            riskValues[i] = scanner.nextInt();
        }
        
        // 读取第四行输入:各产品的最大投资额度
        int[] maxInvestments = new int[m];
        for(int i = 0; i < m; i++) {
            maxInvestments[i] = scanner.nextInt();
        }
        
        scanner.close();
        
        // 初始化最大回报值和最佳投资分配方案
        long maxReturn = 0;
        long[] bestAllocation = new long[m];
        
        // 枚举所有可能的1个产品组合
        for(int i = 0; i < m; i++) {
            // 计算当前产品的总风险值
            int totalRisk = riskValues[i];
            if(totalRisk > X) continue; // 超出可接受风险,跳过
            
            int invest = Math.min(maxInvestments[i], N); // 可投资额度
            long total = (long) invest * returnRates[i]; // 计算回报
            
            if(total > maxReturn) {
                maxReturn = total;
                Arrays.fill(bestAllocation, 0);
                bestAllocation[i] = invest;
            }
        }
        
        // 枚举所有可能的2个产品组合
        for(int i = 0; i < m; i++) {
            for(int j = i+1; j < m; j++) {
                // 计算组合的总风险值
                int totalRisk = riskValues[i] + riskValues[j];
                if(totalRisk > X) continue; // 超出可接受风险,跳过
                
                // 按回报率降序排序
                int first = i, second = j;
                if(returnRates[j] > returnRates[i]) {
                    first = j;
                    second = i;
                }
                
                // 分配投资额度
                int investFirst = Math.min(maxInvestments[first], N);
                int remaining = N - investFirst;
                int investSecond = Math.min(maxInvestments[second], remaining);
                
                // 计算总回报
                long total = (long) investFirst * returnRates[first] + (long) investSecond * returnRates[second];
                
                // 更新最大回报和最佳投资分配方案
                if(total > maxReturn) {
                    maxReturn = total;
                    Arrays.fill(bestAllocation, 0);
                    bestAllocation[first] = investFirst;
                    bestAllocation[second] = investSecond;
                }
            }
        }
        
        // 输出最佳投资分配方案
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < m; i++) {
            sb.append(bestAllocation[i]).append(" ");
        }
        System.out.println(sb.toString().trim());
    }
}
JavaScript 代码
const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});
let inputLines = [];
rl.on('line', (line) => {
    if (line.trim() !== '') {
        inputLines.push(line.trim());
    }
}).on('close', () => {
    // 读取第一行输入:产品数 m,总投资 N,可接受风险 X
    let [m, N, X] = inputLines[0].split(' ').map(Number);
    
    // 读取第二行输入:各产品的回报率
    let returnRates = inputLines[1].split(' ').map(Number);
    
    // 读取第三行输入:各产品的风险值
    let riskValues = inputLines[2].split(' ').map(Number);
    
    // 读取第四行输入:各产品的最大投资额度
    let maxInvestments = inputLines[3].split(' ').map(Number);
    
    // 初始化最大回报值和最佳投资分配方案
    let maxReturn = -1;
    let bestAllocation = Array(m).fill(0);
    
    // 枚举所有可能的1个产品组合
    for(let i = 0; i < m; i++) {
        let totalRisk = riskValues[i];
        if(totalRisk > X) continue; // 超出可接受风险,跳过
        
        let invest = Math.min(maxInvestments[i], N);
        let total = invest * returnRates[i];
        
        if(total > maxReturn) {
            maxReturn = total;
            bestAllocation = Array(m).fill(0);
            bestAllocation[i] = invest;
        }
    }
    
    // 枚举所有可能的2个产品组合
    for(let i = 0; i < m; i++) {
        for(let j = i+1; j < m; j++) {
            let totalRisk = riskValues[i] + riskValues[j];
            if(totalRisk > X) continue; // 超出可接受风险,跳过
            
            // 按回报率降序排序
            let first = i, second = j;
            if(returnRates[j] > returnRates[i]) {
                first = j;
                second = i;
            }
            
            // 分配投资额度
            let investFirst = Math.min(maxInvestments[first], N);
            let remaining = N - investFirst;
            let investSecond = Math.min(maxInvestments[second], remaining);
            
            // 计算总回报
            let total = investFirst * returnRates[first] + investSecond * returnRates[second];
            
            // 更新最大回报和最佳投资分配方案
            if(total > maxReturn) {
                maxReturn = total;
                bestAllocation = Array(m).fill(0);
                bestAllocation[first] = investFirst;
                bestAllocation[second] = investSecond;
            }
        }
    }
    
    // 输出最佳投资分配方案
    console.log(bestAllocation.join(' '));
});
C++ 代码
#include <bits/stdc++.h>
using namespace std;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    // 读取第一行输入:产品数 m,总投资 N,可接受风险 X
    int m, N, X;
    cin >> m >> N >> X;
    
    // 读取第二行输入:各产品的回报率
    vector<int> returnRates(m);
    for(auto &x : returnRates) cin >> x;
    
    // 读取第三行输入:各产品的风险值
    vector<int> riskValues(m);
    for(auto &x : riskValues) cin >> x;
    
    // 读取第四行输入:各产品的最大投资额度
    vector<int> maxInvestments(m);
    for(auto &x : maxInvestments) cin >> x;
    
    // 初始化最大回报值和最佳投资分配方案
    long long maxReturn = -1;
    vector<long long> bestAllocation(m, 0);
    
    // 枚举所有可能的1个产品组合
    for(int i = 0; i < m; i++) {
        int totalRisk = riskValues[i];
        if(totalRisk > X) continue; // 超出可接受风险,跳过
        
        int invest = min(maxInvestments[i], N);
        long long total = (long long)invest * returnRates[i];
        
        if(total > maxReturn) {
            maxReturn = total;
            fill(bestAllocation.begin(), bestAllocation.end(), 0LL);
            bestAllocation[i] = invest;
        }
    }
    
    // 枚举所有可能的2个产品组合
    for(int i = 0; i < m; i++) {
        for(int j = i+1; j < m; j++) {
            int totalRisk = riskValues[i] + riskValues[j];
            if(totalRisk > X) continue; // 超出可接受风险,跳过
            
            // 按回报率降序排序
            int first = i, second = j;
            if(returnRates[j] > returnRates[i]) {
                first = j;
                second = i;
            }
            
            // 分配投资额度
            int investFirst = min(maxInvestments[first], N);
            int remaining = N - investFirst;
            int investSecond = min(maxInvestments[second], remaining);
            
            // 计算总回报
            long long total = (long long)investFirst * returnRates[first] + (long long)investSecond * returnRates[second];
            
            // 更新最大回报和最佳投资分配方案
            if(total > maxReturn) {
                maxReturn = total;
                fill(bestAllocation.begin(), bestAllocation.end(), 0LL);
                bestAllocation[first] = investFirst;
                bestAllocation[second] = investSecond;
            }
        }
    }
    
    // 输出最佳投资分配方案
    for(int i = 0; i < m; i++) {
        cout << bestAllocation[i] << (i < m-1 ? ' ' : '\n');
    }
    
    return 0;
}
        题目描述
在一款虚拟游戏中生活,你必须进行投资以增强在虚拟游戏中的资产以免被淘汰出局。现有一家 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。