美元汇率

题目描述

在以后的若干天里戴维将学习美元与德国马克的汇率。编写程序帮助戴维何时应买或卖马克或美元,使他从 100 美元开始,最后能获得最高可能的价值。

 

输入

第一行是一个自然数 N,1≤N≤100,表示戴维学习汇率的天数。

接下来的行中每行是一个自然数 A,1≤A≤1000。第 i+1 行的表示预先知道的第 i+1 天的平

均汇率,在这一天中,戴维既能用 100 美元买马克也能用马克购买 100 美元。

 

输出

第一行也是唯一的一行应输出要求的钱数(单位为美元,保留两位小数)。

注意:考虑到实数算术运算中进位的误差,结果在正确结果 0.05 美元范围内的被认为是正确的,戴维必须在最后一天结束之前将他的钱都换成美元。

 

样例输入

5

400

300

500

300

250

 

样例输出

266.67

 

提示

样例解释 (无需输出)

Day 1 ... changing 100.0000 美元= 400.0000 马克

 Day 2 ... changing 400.0000 马克= 133.3333 美元

 Day 3 ... changing 133.3333 美元= 666.6666 马克

 Day 5 ... changing 666.6666 马克= 266.6666 美元

分析:首先我们都能想到的是让100美元能换尽可能多的马克,然后用尽可能少的马克换回美元。

不过换句话说,想要挣钱,只要让美元换马克的汇率大于马克换回美元的汇率即可。

那究竟是大多少呢?两者差距越大越好。比如500 400 300,当汇率是500的时候我们将美元换成了马克,那么很显然,挣钱最多的方法是在汇率是300的时候换过来,而不是在400的时候换。那也就是说,如果汇率一直下降,我们要在汇率最低的时候将马克换回美元。

如果我们将美元换马克,马克换回美元称作一次交换,那么一次交换后的钱(xnew)就等于

            xnew = x(原来钱数) * a[i] / a[j]

a[i] 是美元换马克的汇率,a[j] 是马克换美元的汇率。

那么如果汇率不在下降了呢?很显然,如果我们这是再将马克换回美元的话,那就不如汇率回升钱赚钱了。那也就是说,这一次交换也就结束了,然后以汇率开始回升的点作为美元换马克的汇率,进行下一次交换。

这么一说,这道题就变成了求一个序列的不上升子区间的问题了。每一个不上升的子区间代表一次交换,子区间第一个值是美元换马克的汇率,最后一个值是马克换回美元的值。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 #define rep(i, a, n) for(int i = a; i <= n; ++i)
 8 #define per(i, n, a) for(int i = n; i >= a; --i)
 9 typedef long long ll;
10 const int maxn = 1e3 + 5;
11 
12 int a[maxn], n;
13 int pos = 0;
14 double hl[maxn], ans = 100.0000;        //hl[]存一次交换的汇率 
15 int main()
16 {
17     freopen("dollars.in", "r", stdin);
18     freopen("dollars.out", "w", stdout);
19     scanf("%d", &n);
20     rep(i, 1, n) scanf("%d", &a[i]);
21     int head = a[1];
22     rep(i, 1, n)
23         if((a[i + 1] > a[i]) || (i == n)) {hl[++pos] = (double) head / a[i]; head = a[i + 1];}
24     rep(i ,1 ,pos) ans *= hl[i];
25     printf("%.2lf
", ans);
26     return 0;
27 }

一道比较有意思的小贪心。。

原文地址:https://www.cnblogs.com/mrclr/p/8570683.html