洛谷:P1853 【投资的最大效益】

本文通过一个具体案例,模拟了如何在给定多种债券、初始总资产和年数的情况下,计算经过n年投资后总资产的最大值。利用完全背包算法,通过n层循环不断更新投资策略,最终得出最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目背景

约翰先生获得了一大笔遗产,他暂时还用不上这一笔钱,他决定进行投资以获得更大的效益。银行工作人员向他提供了多种债券,每一种债券都能在固定的投资后,提供稳定的年利息。当然,每一种债券的投资额是不同的,一般来说,投资越大,收益也越大,而且,每一年还可以根据资金总额的增加,更换收益更大的债券。

题目描述

例如:有如下两种不同的债券:①投资额$4000,年利息$400;②投资额$3000,年利息$250。初始时,有$10000的总资产,可以投资两份债券①债券,一年获得$800的利息;而投资一份债券①和两份债券②,一年可获得$900的利息,两年后,可获得$1800的利息;而所有的资产达到$11800,然后将卖掉一份债券②,换购债券①,年利息可达到$1050;第三年后,总资产达到$12850,可以购买三份债券①,年利息可达到$1200,第四年后,总资产可达到$14050。

现给定若干种债券、最初的总资产,帮助约翰先生计算,经过n年的投资,总资产的最大值。

输入输出格式

输入格式:

第一行为三个正整数s,n,d,分别表示最初的总资产、年数和债券的种类。

接下来d行,每行表示一种债券,两个正整数a,b分别表示债券的投资额和年利息。

输出格式:

仅一个整数,表示n年后的最大总资产。


我们先分析一下题目: 对于第一年,可以将第一年的钱尽可能地拿去投资,然后获得能够得到的最大利息;然后对于第二年,第二年可以使用的金钱相当于第一年的初始金钱加上利息,然后再用这些钱尽可能地拿去投资,获得能够得到的最大利息...于是,第i年时就可以将第i-1年投资所得到的利息再加上第i-1年的初始金钱尽可能拿去投资,获得能够得到的最大金钱.于是第n年就很容易地推导了出来. 那么对于这些操作,我们只需要将一个完全背包放入一个n层的循环里,然后每层循环结束后对完全背包的第二层循环的上限进行更新,经过n次循环就可以得出答案了.

#include <iostream>
#include <cstring>
#define maxs 1000000 + 5
#define maxn 40 + 5
#define maxd 10 + 5
#define maxm 10000000 + 5
#define inf 0x80808080
using namespace std;

int c[maxd], t[maxd];
int s, n, d;
int dp[maxm];

int main(){
    ios::sync_with_stdio(false);
    cin >> s >> n >> d;
    for(int i = 1; i <= d; i++) cin >> c[i] >> t[i];

    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= d; j++){
            for(int k = c[j]; k <= s - s % 1000; k += 1000){
                if(dp[k] < dp[k - c[j]] + t[j]){
                    dp[k] = dp[k - c[j]] + t[j];
                }
            }
        }
        s += dp[s - s % 1000];
    }
    cout << s << endl;

    return 0;
}

另外,由于题目说每种债劵的投资额都是1000的倍数,所以在完全背包的第二层循环中变量可以 -= 1000.

### 关于 P2089 烧鸡的 C++ 解题思路 #### 题目概述 题目描述了一只喜欢食用烤鸡的角色,其烹饪过程中需加入不同种类的调料。每种调料可选的质量范围固定,在此条件下求出所有满足特定总质量组合的方法数及其具体方案。 #### 深度优先搜索算法的应用 为了找出所有的符合条件的解集,采用深度优先搜索(DFS)是一种有效的方式。通过递归调用来遍历每一个可能的选择路径直到达到终止状态——即当所选取的所有调料总量等于目标值 `n` 或者超出界限时停止进一步探索该分支并返回上一层继续尝试其他可能性[^1]。 对于这个问题而言: - 定义全局变量用于记录可行解的数量以及具体的分配方式; - 使用辅助函数 `dfs()` 来执行实际的搜索过程,参数包括当前处理的位置索引和累积起来已使用的调料重量; - 在每次进入新的层次前设置好边界条件防止不必要的计算浪费时间资源;一旦发现超过预定的最大允许量则立即中断这条路线不再深入下去; - 当成功找到一组匹配的数据之后将其保存下来供后续输出展示使用。 下面是基于上述逻辑编写的完整程序代码示例: ```cpp #include <iostream> using namespace std; // 变量声明部分 int num1 = 0; // 记录总的解决方案数目 const int MAXN = 2333; int num2[MAXN][11]; // 存储各个方案的具体数值分布情况 int cnt, n; int a[11]; void dfs(int t, int now) { if (t > 10) { // 达到最大层数后的判断操作 if (now == n) { ++num1; for (int i = 1; i <= 10; ++i) num2[num1][i] = a[i]; } return; } for (int i = 1; i <= 3; ++i) { // 尝试三种不同的调料用量 if (now + i > n) break; // 提前结束循环以减少无谓运算次数 a[t] = i; dfs(t + 1, now + i); a[t] = 0; // 清除标记以便下一轮迭代重置环境 } } int main() { cin >> n; dfs(1, 0); cout << num1 << endl; for (int i = 1; i <= num1; ++i) { for (int j = 1; j <= 10; ++j) cout << num2[i][j] << " "; cout << "\n"; } return 0; } ``` 这段代码实现了对给定问题的有效解答,并且能够正确地打印出所有合法的结果集合。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值