BF算法的实际应用 套汇

如果没接触过bf算法,先看看它的介绍吧?
bellman ford算法百度百科介绍

图中的加权有向边代表汇率,我们可以发现如果把 100 单位的货币 A 换成 B,再换成 C,最后换回 A,就可以得到 100×0.9×0.8×1.4 = 100.8 单位的 A!
如果交易的金额大一些的话,赚的钱是很可观的,这种空手套白狼的操作就是套汇。
现实中交易会有种种限制,而且市场瞬息万变,但是套汇的利润还是很高的,关键就在于如何快速找到这种套汇机会呢?
在这里插入图片描述

借助图的抽象,我们发现套汇机会其实就是一个环,且这个环上的权重之积大于 1,只要在顺着这个环交易一圈就能空手套白狼。
图论中有一个经典算法叫做 Bellman-Ford 算法,可以用于寻找负权重环。对于我们说的套汇问题,可以先把所有边的权重 w 替换成 -ln(w),这样「寻找权重乘积大于 1 的环」就转化成了「寻找权重和小于 0 的环」
就可以使用 Bellman-Ford 算法在 O(EV) 的时间内寻找负权重环,也就是寻找套汇机会。


Bellman-Ford 伪代码理解

bool Bellman-Ford(G,w,s)        //图G ,边集 函数 w ,s为源点
  for each vertex v ∈ V(G):     //初始化距离源点距离均为无穷大
    d[v]+∞
  d[s]0                       //源点距离自身为0
  for i = 1|V|:              //松弛操作需要重复多次
    for each edge (u,v)E(G):
      if d[v] > d[u] + w(u,v):
        d[v] = d[u] + w(u,v)
  for each edge(u,v)E(G):    //判断是否存在负权环路
    if d[v] > d[u] + w(u,v):
      return false
  return true

SPFA实际上是用队列对bf的优化,思路差不多

int SPFA(int s) {
     queue<int> q; 
     bool inq[maxn] = {false}; 
     for(int i = 1; i <= N; i++) dis[i] = 2147483647; 
     dis[s] = 0; 
     q.push(s); inq[s] = true; 
     while(!q.empty()) { 
         int x = q.front(); q.pop(); 
         inq[x] = false;
         for(int i = front[x]; i !=0 ; i = e[i].next) {
             int k = e[i].v;
             if(dis[k] > dis[x] + e[i].w) {
                 dis[k] = dis[x] + e[i].w;
                 if(!inq[k]) {
                     inq[k] = true;
                     q.push(k);
                 }
             }
         }
     }
     for(int i =  1; i <= N; i++) cout << dis[i] << ' ';
     cout << endl;
     return 0;
 }
原创文章 23 获赞 5 访问量 1325

猜你喜欢

转载自blog.csdn.net/CrazyMooo/article/details/105765182