洛谷 P1853 投资的最大效益 蒟蒻题解
题目背景
约翰先生获得了一大笔遗产,他暂时还用不上这一笔钱,他决定进行投资以获得更大的效益。银行工作人员向他提供了多种债券,每一种债券都能在固定的投资后,提供稳定的年利息。当然,每一种债券的投资额是不同的,一般来说,投资越大,收益也越大,而且,每一年还可以根据资金总额的增加,更换收益更大的债券。
题目描述
例如:有如下两种不同的债券:
- 投资额 $$4000$,年利息 $$400$;
- 投资额 $$3000$,年利息 $$250$。
初始时,有 $$10000$ 的总资产,可以投资两份债券 1 债券,一年获得 $$800$ 的利息;而投资一份债券 1 和两份债券 2,一年可获得 $$900$ 的利息,两年后,可获得 $$1800$ 的利息;而所有的资产达到 $$11800$,然后将卖掉一份债券 2,换购债券 1,年利息可达到 $$1050$;第三年后,总资产达到 $$12850$,可以购买三份债券 1,年利息可达到 $$1200$,第四年后,总资产可达到 $$14050$。
现给定若干种债券、最初的总资产,帮助约翰先生计算,经过 $n$ 年的投资,总资产的最大值。
输入格式
第一行为三个正整数 $s, n, d$,分别表示最初的总资产、年数和债券的种类。
接下来 $d$ 行,每行表示一种债券,两个正整数 $a, b$ 分别表示债券的投资额和年利息。
输出格式
仅一个整数,表示 $n$ 年后的最大总资产。
样例 #1
样例输入 #1
10000 4 2
4000 400
3000 250
样例输出 #1
14050
提示
对于 $100 %$ 的数据,$1 \le s \le {10}^6$,$2 \le n \le 40$,$1 \le d \le 10$,$1 \le a \le {10}^4$,且 $a$ 是 $1000$ 的倍数,$b$ 不超过 $a$ 的 $10%$。
解题思路:
简单的完全背包问题,但是需要动态考虑背包体积的扩大
仔细考虑dp维护什么,本此题解以利润为例
每年本金 = 债券总额 + 剩余本金 + 创收利润 同时债券总额 + 剩余本金 = 原本本金(因为债券可以无损买卖)
所以有 本金+=利润
这就是每年本金的更新
其余解释置于代码注释
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<stdio.h>
#include<vector>//Vector动态容器
#include<algorithm>
#include<stack>//栈
#include<unordered_map>//哈希表
#include<map>
#include<queue>//队列
using namespace std;
int dp[10000001];
int s, n, d;
int w[3000000];//每个债券的本金
int val[3000000];//每个债券的利润
int a;
int main(){
cin >> s >> n >> d;//总本金 年份 种类
for (int i = 1; i <= d; i++){//a是1000的倍数 放缩
cin >> w[i] >> val[i];
}
//总本金算背包容量 债券占据背包容量的同时 会扩大背包容量(创收利润)
//债券还可以卖出 将背包容量减轻w[i]后 背包容量对应增大w[i]
//债券动态选择 相当于不同的元素 可以重复选取
//动态完全背包
//n年 每年都会在第二年创收利润
for (int q = 1; q <= n; q++) {
//每年本金 = 债券总额 + 剩余本金 + 创收利润 但是债券总额 + 剩余本金 = 原本本金
//所以最终就是 s+=dp[s]
for (int i = 1; i <= d; i++) {//计算种类
for (int j = w[i]/1000; j <= s / 1000; j++) {//计算本金(背包体积)
dp[j] = max(dp[j], dp[j - w[i] / 1000] + val[i]);//dp维护第二年创收利润
}
}
s = s + dp[s / 1000];
memset(dp, 0, sizeof(dp));//每年重置
}
cout << s << endl;
}
包过的!!!
标签:le,洛谷,int,题解,背包,债券,本金,P1853,include From: https://www.cnblogs.com/lgdxxs12138/p/18293222