- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
[从Cash谈一类分治算法的应用
从《Cash》谈一类分治算法的应用
分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同求出子问题的解,就可得到原问题的解
问题描述
小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称 A 券)和 B 纪念券(以下简称 B 券).每个持有金券的顾客都有 一个自己的帐户.金券的数目可以是一个实数每天随着市场的起伏波动,两种金券都有自己当时的价值,即每一单位金券 当天可以兑换的人民币数目.我们记录第 K 天中 A 券和 B 券的价值分别为 AK 和 BK(元/单位金券).
为了方便顾客,金券交易所提供了一种非常方便的交易方式:比例交易法. 比例交易法分为两个方面:
A) 卖出金券:顾客提供一个[0,100]内的实数 OP 作为卖出比例,其意 义为:将 OP%的 A 券和 OP%的 B 券以当时的价值兑换为人民币;
B) 买入金券:顾客支付 IP 元人民币,交易所将会兑换给用户总价值为
IP 的金券,并且,满足提供给顾客的 A 券和 B 券的比例在第 K 天恰好为 RateK;
例如,假定接下来 3 天内的 Ak、Bk、RateK 的变化分别为:
时间 Ak Bk RAtek 第一天 1 1 1 第二天 1 2 2 第三天 2 2 3 假定在第一天时,用户手中有 100 元人民币但是没有任何金券. 用户可以执行以下的操作:时间 用户操作 人民币(元) A 券的数量 B 券的数量 开户 无 100 0 0 第一天 买入 100 元 0 50 50 第二天 卖出 50% 75 25 25 第二天 买入 60 元 15 55 40 第三天 卖出 100% 205 0 0 注意到,同一天内可以进行多次操作.小 Y 是一个很有经济头脑的员工,通过较长时间的运作和行情测算,他已经 知道了未来 N 天内的 A 券和 B 券的价值以及 Rate.他还希望能够计算出来,如 果开始时拥有 S 元钱,那么 N 天后最多能够获得多少元钱.
←S * Rate[1] / (A[1] * Rate[1] + B[1])
Ans←S
For i ← 2 to n
For j ← 1 to i-1
x ← f [j] * A[i] + f [j] / Rate[j] * B[i]
If x Ans
Then Ans ← x
End For
f [i] ← Ans * Rate[i] / (A[i] * Rate[i] + B[i])
End For
Print(Ans)
O(n2)的算法显然无法胜任题目的数据规模.我们来分析对于i的两个决策j和k,决策j比决策k优当且仅当:
(f [j] – f [k]) * A[i] + (f [j] / Rate[j] – f [k] / Rate[k]) * B[i] 0.
不妨设f [j] f [k],g[j] = f [j] / Rate[j],那么
(g[j] – g[k]) / (f[j] – f[k]) -a[i] / b[i].
这样我们就可以用平衡树以f [j]为关键字来维护一个凸线,平衡树维护一个点集(f [j], g[j]),f [j]是单调递增的,相邻两个点的斜率是单调递减的.每次在平衡树中二分查找与-a[i] / b[i]最接近的两点之间的斜率.
这样动态规划的时间复杂度就降低为O(nlog2n),但是维护凸线的平衡树实在不容易在考场中写对?,编程复杂度高,不易调试(我的Splay代码有6k多).这个问题看上去只能用高级数据结构来维护决策的单调性,事实上我们可以利用分治的思想来提出一个编程复杂度比较低的方法:
对于每一个i,它的决策j的范围为1~i-1.我们定义一个Solve过程:
Solve(l, r)表示对于的l ≤ i ≤ r,用l ≤ j ≤ i-1的决策j来更新f [i]的值.这样我们的目标就是Solve(1, n):可以先Solve(1, n/2)后计算出f [1] .. f[n/2],那么1~n/2的每一个数一定是n/2+1~n的每个i的决策,用1~n/2的决策来更新n/2+1~n的f[i]值后Solve(n/2+1, n).这恰好体现的是一种分治的思想:
用1~n/2的决策来更新n/2+1~n的f[i]值:类似用平衡树的方法,我们可以对1~n/2的所有决策建立一个凸线,对n/2+1~n的所有i按照-a[i] / b[i]从大到小排序,凸线的斜率是单调的,-a[i]/b[i]也是单调的,这样我们就可以通过一遍扫描来计算出对于每一个i在1~n/2里面最优的决策j.
现在面临的问题是如何对于一段区间[l, r]维护出
文档评论(0)