记录88
cpp
#include<bits/stdc++.h>
using namespace std;
double dp[110][2],a[110];
int main(){//两种最大的状态,美元,马克
int n;
cin>>n;
dp[0][0]=100;//初始时候的美元数
dp[0][1]=0;//初始时候的马克数
for(int i=1;i<=n;i++){
cin>>a[i];
dp[i][0]=max(dp[i-1][0],dp[i-1][1]*(100.0/a[i]));//除一个数,就是乘它的倒数
dp[i][1]=max(dp[i-1][1],dp[i-1][0]*(a[i]/100.0));
}
cout<<fixed<<setprecision(2)<<dp[n][0];
//printf("%.2f",dp[n][0]);
return 0;
}
题目传送门
https://www.luogu.com.cn/problem/P1968
突破口
在以后的若干天里戴维将学习美元与德国马克的汇率。编写程序帮助戴维何时应买或卖马克或美元,使他从 100 美元开始,最后能获得最高可能的价值。
思路
🎯 问题本质
- 戴维初始有 100 美元
- 接下来
N天,每天有一个汇率A_i:- 100 美元 ⇄ A_i 马克
- 即:1 美元 =
A_i / 100马克,1 马克 =100 / A_i美元
- 每天他可以选择:
- 把所有美元换成马克
- 把所有马克换成美元
- 什么都不做
- 目标 :在第
N天结束前,必须持有美元,且金额最大
💡 关键约束:最后必须是美元!
这是一个典型的 动态规划(DP) 问题,状态只有两种:持有美元 或 持有马克。
🧠 动态规划设计
状态定义
dp[i][0]:第i天结束后,持有美元的最大金额dp[i][1]:第i天结束后,持有马克的最大金额
初始状态
dp[0][0] = 100(开始有 100 美元)dp[0][1] = 0(没有马克)
状态转移(第 i 天)
-
美元状态
dp[i][0]可以来自:- 昨天就持有美元,今天不动 →
dp[i-1][0] - 昨天持有马克,今天全部换成美元 →
dp[i-1][1] × (100 / a[i])
- 取两者最大值
- 昨天就持有美元,今天不动 →
-
马克状态
dp[i][1]可以来自:- 昨天就持有马克,今天不动 →
dp[i-1][1] - 昨天持有美元,今天全部换成马克 →
dp[i-1][0] × (a[i] / 100)
- 取两者最大值
- 昨天就持有马克,今天不动 →
✅ 注意:每天最多操作一次(全换或不换),因为部分换不会更优(汇率固定,全换收益最大)
最终答案
dp[N][0](第 N 天必须是美元)
代码分析
cpp
#include<bits/stdc++.h>
using namespace std;
double dp[110][2], a[110];
dp[i][0/1]:第 i 天的美元/马克最大值a[i]:第 i 天的汇率(100 美元 ↔ a[i] 马克)- 数组大小 110(因 N ≤ 100)
cpp
int main(){
int n;
cin >> n;
cpp
dp[0][0] = 100; // 初始 100 美元
dp[0][1] = 0; // 初始 0 马克
🔁 每天更新状态
cpp
for(int i = 1; i <= n; i++){
cin >> a[i];
- 读入第
i天的汇率a[i]
cpp
dp[i][0] = max(dp[i-1][0], dp[i-1][1] * (100.0 / a[i]));
- 计算第
i天持有美元的最大值:- 不换:
dp[i-1][0] - 用马克换:
dp[i-1][1]马克 ×(100 / a[i])美元/马克
- 不换:
cpp
dp[i][1] = max(dp[i-1][1], dp[i-1][0] * (a[i] / 100.0));
- 计算第
i天持有马克的最大值:- 不换:
dp[i-1][1] - 用美元换:
dp[i-1][0]美元 ×(a[i] / 100)马克/美元
- 不换:
💡 使用
100.0而不是100是为了强制浮点运算,避免整数除法
🔚 输出结果
cpp
cout << fixed << setprecision(2) << dp[n][0];
return 0;
}
- 输出第
n天的美元金额,保留两位小数 fixed + setprecision(2)确保格式为xxx.xx
⚠️ 题目允许 ±0.05 误差,所以浮点精度足够
🧪 样例验证(n=5,汇率=[400,300,500,300,250])
| 天 | 汇率 A | dp[i][0](美元) | dp[i][1](马克) | 操作 |
|---|---|---|---|---|
| 0 | --- | 100.00 | 0.00 | 初始 |
| 1 | 400 | max(100, 0) = 100 | max(0, 100×4) = 400 | 换成马克 |
| 2 | 300 | max(100, 400×100/300 ≈133.33) = 133.33 | max(400, 100×3=300) = 400 | 马克换美元 |
| 3 | 500 | max(133.33, 400×0.2=80) = 133.33 | max(400, 133.33×5≈666.67) = 666.67 | 美元换马克 |
| 4 | 300 | max(133.33, 666.67×100/300≈222.22) = 222.22 | max(666.67, 133.33×3=400) = 666.67 | --- |
| 5 | 250 | max(222.22, 666.67×100/250=266.67) = 266.67 | ... | 马克换美元 |
→ 输出 266.67 ✅
总结
| 要点 | 说明 |
|---|---|
| 状态设计 | dp[i][0](美元),dp[i][1](马克) |
| 转移逻辑 | 每天可选择"换"或"不换",取最大值 |
| 汇率转换 | 100 美元 ↔ A 马克 → 1 美元 = A/100 马克 |
| 最终要求 | 第 N 天必须是美元 → 输出 dp[N][0] |
| 精度处理 | 用 double + setprecision(2) |
这段代码正确建模了货币兑换的最优决策过程,是动态规划在金融场景中的经典应用。