100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > EOJ1270-Arbitrage(套利交易)

EOJ1270-Arbitrage(套利交易)

时间:2023-06-22 18:04:29

相关推荐

EOJ1270-Arbitrage(套利交易)

题目大意:有很多种外币,它们之间部分可以互相兑换,假如你有一个单位的某种货币,问是否可以通过有限次兑换回到当初你拥有的那种货币,使得最后得到的货币多于一个单位。例如:1美元换0.5英镑,1英镑换10法币,1法币换0.21美元。从1美元出发,兑换过程为:1×0.5×10×0.21=1.05>1,所以该套利交易可行。

ps:以上汇率仅作说明,不代表市场上真正的汇率。

题目分析:按题目意思可以抽象成一个带权有向图求“最长路径”,每次从一个点出发,经过一个环路再回到出发点,实现一次套利交易,所以检查每个点的所有环,直到找到一次可行的套利交易或者全部检查完都没有可行的套利交易。从这个想法出发去找所以的环实现起来很麻烦,所以把问题简化,可以想到,这道题类似求给定节点对的最短路径,那么我们可以借助Floyd算法来实现这一过程,不过需要做一点小小的改动。

//dis[i][j] 表示货币i到货币j的汇率void init(){for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++){if(i == j)dis[i][j] = 1.0;//与自身的汇率为1.0elsedis[i][j] = 0.0;//当前i不可交换j}}

对dis数组进行初始化,如果两种货币不能交换,则置dis[i][j]=0.0 相当于最短路径里面置为无穷大,表示i不可到达j。

void Folyd(){for(int k = 1; k <= n; k++)for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++){if(dis[i][j] < dis[i][k]*dis[k][j])//"松弛操作"dis[i][j] = dis[i][k]*dis[k][j];}}

Floyd核心代码,注意松弛操作的过程,如果货币i先兑换到货币k,再由货币k兑换到货币j得到的货币更多,那么就进行松弛操作,即dis[i][j] = dis[i][k]*dis[k][j];

完整代码如下:

#include <iostream>#include <cstdio>#include <cstdlib>#include <map>#include <string>using namespace std;#define MAXN 50double dis[MAXN][MAXN];//存放汇率map<string, int> money;//索引货币顶点int n, m;//n个顶点、m条边void Folyd(){for(int k = 1; k <= n; k++)for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++){if(dis[i][j] < dis[i][k]*dis[k][j])//"松弛操作"dis[i][j] = dis[i][k]*dis[k][j];}}void init(){for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++){if(i == j)dis[i][j] = 1.0;//与自身的汇率为1.0elsedis[i][j] = 0.0;//当前i不可交换j}}int main(int argc, char const *argv[]){int u, v, count=1;int i, flag;double rate;string s, str;while(scanf("%d", &n) && n != 0){flag = 0;//标记money.clear();//清空init();//dis数组初始化for(i = 1; i <= n; i++){cin>>s;money.insert(pair<string, int>(s, i));//货币名与顶点配对}scanf("%d", &m);while(m--){cin>>s>>rate>>str;u = money[s];v = money[str];dis[u][v] = rate;//u到v汇率为rate}Folyd();for(i = 1; i <= n; i++)if(dis[i][i] > 1.0)//有可行的套利交易{flag = 1;break;}if(flag == 1)printf("Case %d: Yes\n", count++);elseprintf("Case %d: No\n", count++);}return 0;}

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

对于dis的对角线元素的判断还可以放在Floyd函数中:

void Folyd(){for(int k = 1; k <= n; k++)for(int i = 1; i <= n; i++)for(int j = 1; j <= n; j++){if(dis[i][j] < dis[i][k]*dis[k][j])//"松弛操作"dis[i][j] = dis[i][k]*dis[k][j];if(i == j && dis[i][j] > 1.0){flag = 1;//定义为全局变量return ;}}}

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

测试数据:

输入:

3

USDollar

BritishPound

FrenchFranc

3

USDollar 0.5 BritishPound

BritishPound 10.0 FrenchFranc

FrenchFranc 0.21 USDollar

3

USDollar

BritishPound

FrenchFranc

6

USDollar 0.5 BritishPound

USDollar 4.9 FrenchFranc

BritishPound 10.0 FrenchFranc

BritishPound 1.99 USDollar

FrenchFranc 0.09 BritishPound

FrenchFranc 0.19 USDollar

0

输出:

Case 1: Yes

Case 2: No

Folyd算法参考:/niushuai666/article/details/6772706

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。