利用动态规划解决实际问题之多次兑换获取最大外汇收益
来源:互联网 发布:淘宝运营是做什么的 编辑:程序博客网 时间:2024/04/29 21:40
题目:
15.3-6假定你希望兑换外汇,你意识到与其直接兑换,不如进行多种外币的一系列兑换,最后兑换到你想要的那种外币,可能会获得更大收益。假定你可以交易n种不同的货币,编号为1,2.....n,兑换从1号货币开始,最终兑换为n号货币。对每两种货币i和j给定汇率rij,意味着你如果有d个单位的货币i,可以兑换dr0个单位的货币j.进行一系列的交易需要支付一定的佣金,金额取决于交易次数。令ck表示k次交易需要支付的佣金。证明:如果对所有k=1,2...n,ck=0,那么寻找最优兑换序列的问题具有最优子结构性质。然后请证明:如果佣金ck为任意值,那么问题不一定具有最优子结构性质。
题目虽然没有要求写出算法,但我也给出算法。
//15.3-6多次兑换货币换取最大收益,本次使用的方法是带备忘的递归#include <iostream>using namespace std;#define n 4struct Currency_Exchange{double **r;//储存汇率int *s;//储存外汇最佳方式的变量Currency_Exchange(){r=new double *[n];for (int i=0;i<n;i++){r[i]=new double[n];}s=new int [n];}};struct Best_Currency_Exchange{static double Max;//最大收益static double Min;//最小收益int *t;static int end;Best_Currency_Exchange(){ t=new int[n];}};double Best_Currency_Exchange::Max=-0x7fffffff;double Best_Currency_Exchange::Min=0x7fffffff;int Best_Currency_Exchange::end=0x7fffffff;void init(Currency_Exchange T,Best_Currency_Exchange Result)//结构体的初始化{for (int i=0;i<n;i++){for (int j=0;j<n;j++){T.r[i][j]=-0x7fffffff;}T.s[i]=-0x7fffffff;Result.t[i]=-0x7fffffff;}Result.end=-1;}inline void swap(int* array, unsigned int i, unsigned int j) { int t = array[i]; array[i] = array[j]; array[j] = t; } void Print(int i){switch (i){case 0:cout<<"欧元(EUR-0)-->";break;case 1:cout<<"坡元(SGD-1)-->";break;case 2:cout<<"加元(CAD-2)-->";break; case 3:cout<<"澳元(AUD-3)-->";break;case 4:cout<<"日元(JPY-4)-->";break;case 5:cout<<"台币(CHF-5)-->";break;case 6:cout<<"英镑(GBP-6)-->";break;default: cout<<"超出范围,输入错误!"<<endl;break;}} Best_Currency_Exchange FullArray(int* array, size_t array_size, unsigned int index,Currency_Exchange T,Best_Currency_Exchange Result) { static int k=0,t=0; static double m=1.0,M=1.0;//m保存总收益值,M保存除最后一个元素外的总收益if(index>=0) { k++;int j=0;cout<<"k="<<k<<":";if (index>=1){m=M;if(m==1.0) { m*=T.r[0][array[0]]; M=m;} T.s[0]=0;for (int h=0;h<t;h++){//这个循环以及下面的print函数只是为了查看所有可能的兑换方式。Print(array[h]);cout<<' ';}for(unsigned int i = t; i < index; ++i) { //i=t 表示记录了i=0~t-1所有子结构所得的收益值,使所有重叠的子结构仅仅进行一次计算以达到动态规划目的Print(array[i]);cout<<' '; T.s[i+1]=array[i];if (i==index-1)m*=T.r[array[i]][n-1];else { M*=T.r[array[i]][array[i+1]];m=M;t++;}}if(i<n-1){ T.s[i+1]=n-1;}i++;j=i;}else if(index==0){M=m=T.r[0][n-1];T.s[j++]=0;T.s[j++]=n-1;}cout<<"m="<<m;if (Result.Max<m){Result.Max=m;Result.end=j;for (int q=0;q<=Result.end;q++){Result.t[q]=T.s[q];}}if (Result.Min>m){Result.Min=m;} cout << '\n'; if (index==0){M=1.0;} } if (index==array_size) {//每次两者相等条件成立后,以后的所有结构都没有之前的子结构了,所以再次递归前与递归后不可能有重叠子结构。t=0;m=1.0;M=1.0;//所以满足条件后回归初始状态。return Result; } for(unsigned int i = index; i < array_size; ++i) { swap(array, i, index); FullArray(array, array_size, index + 1,T,Result); swap(array, i, index); } return Result;} void main(){ Currency_Exchange T;Best_Currency_Exchange Result;init(T,Result);//结构体的初始化for (int i=0;i<n;i++){for (int j=0;j<n;j++){cout<<"请输入";Print(i);cout<<"-->";Print(j);cin>>T.r[i][j];cout<<endl;}}int array[n-2]={1,2};Best_Currency_Exchange Result1=FullArray(array, n-2,0, T,Result);cout<<"最佳兑换方式:";for (int k=0;k<=Result1.end;k++){if (Result1.t[k]>-0x7fffffff){Print(Result1.t[k]);}}cout<<endl;cout<<"最大收益为:"; cout<<Result1.Max<<endl;cout<<"最小收益为:";cout<<Result1.Min<<endl;cout<<"两者差值为:"<<endl;cout<<Result1.Max-Result1.Min<<endl;}
数据实例图:
不加额外手续费的结果图:
如果算上额外任意手续费就会如下图:
总结:
故手续费为0时,可以用最优子结构,手续费任意时就不能用了。本程序适合总共只有7种外汇兑换,而如果再多兑换,那么就要更改print函数,不过我们可以只用数字1,2...n代表外汇,删掉print函数。另外感觉动态规划用到这里感觉就是大材小用了,因为实际主要外汇就不超过8种,所有可能的排列方式为p(6,1)+p(6,2)+p(6,3)+p(6,4)+p(6,5)+p(6,6) =1956种。所以以现在的普通计算机计算速度,完全可以在几秒内解决。有人可能问,为什么是6种外汇排列而不是8种外汇排列?那是因为要计算外汇A以何种方式兑换到外汇B,这AB外汇位置顺序是固定不变的,所以不用对AB这两种外汇排列。但是确实多种外汇兑换符合动态规划原理。并且在实际应用过程中,外汇汇率是千变万化的,所以仅用此程序是远远不能计算最大利润的。
- 利用动态规划解决实际问题之多次兑换获取最大外汇收益
- 小米笔试-股票最大收益(动态规划)
- 钢条切割获得最大收益(动态规划)
- 利用C语言解决实际问题
- 动态规划算法应用于一个实际问题
- PHP入门--外汇兑换
- 【算法导论学习-27】动态规划经典问题01:钢条切割的最大收益
- leetcode_121. Best Time to Buy and Sell Stock 求股票的最大收益 动态规划
- 动态规划算法举例解析(最大收益和最小损失选择)
- 动态规划解决最大子矩阵问题
- 动态规划解决最大字段和
- 金钱兑换问题 动态规划 打印兑换后的硬币
- 利用动态规划解决连乘问题
- 利用动态规划解决交叉字符串问题
- 算法_动态规划_货币兑换
- 动态规划:HDU1248-钱币兑换问题
- bzoj1942 货币兑换【动态规划+CDQ分治】
- 动态规划之多重背包
- 某移动社交应用服务端架构浅析
- [高斯消元] poj 1830 开关问题
- hdu1575
- css兼容性
- python基础教程_学习笔记26:好玩的编程
- 利用动态规划解决实际问题之多次兑换获取最大外汇收益
- 工作能力怎么提高-薪介网
- 来自亲妈的爱,永远那么炽烈、火辣,令人热泪盈眶。 7分钟前致很多单身IT男下班以后不知道去哪还抱怨找不到女友的童鞋
- Java Applet工作原理
- JSP简单练习-用Servlet获取表单数据
- 成功者的归零心态-薪介网
- HTML的script
- MTK平台缩写
- jQuery判断checkbox是否选中