Arbitrage

Arbitrage is the use of discrepancies in currency exchange rates to transform one unit of a currency into more than one unit of the same currency. For example, suppose that 1 US Dollar buys 0.5 British pound, 1 British pound buys 10.0 French francs, and 1 French franc buys 0.21 US dollar. Then, by converting currencies, a clever trader can start with 1 US dollar and buy 0.5 * 10.0 * 0.21 = 1.05 US dollars, making a profit of 5 percent. 

Your job is to write a program that takes a list of currency exchange rates as input and then determines whether arbitrage is possible or not. 

Input

The input file will contain one or more test cases. Om the first line of each test case there is an integer n (1<=n<=30), representing the number of different currencies. The next n lines each contain the name of one currency. Within a name no spaces will appear. The next line contains one integer m, representing the length of the table to follow. The last m lines each contain the name ci of a source currency, a real number rij which represents the exchange rate from ci to cj and a name cj of the destination currency. Exchanges which do not appear in the table are impossible.
Test cases are separated from each other by a blank line. Input is terminated by a value of zero (0) for n. 

Output

For each test case, print one line telling whether arbitrage is possible or not in the format "Case case: Yes" respectively "Case case: No". 

Sample Input

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

Sample Output

Case 1: Yes
Case 2: No

题意:

已知n种货币,以及m种货币汇率及方式,问能否通过货币转换,使得财富增加。

解题思路:

目测是一条不错的生财之道~~~(打住)

财富增加的话肯定是以同种货币作比较,否则没有意义,因此题意大致可以变成在一个n个顶点的图中能否找到一个正权环,这里的正权环指财富增加,很明显可用Bellman-ford 算法(专门解决存在环的最短路径问题)。

Bellman-ford 算法:一个具有n个顶点的图如果不存在环,则从顶点x,到顶点y,最多经过n-1条边(要考虑连通性,每个顶点最多经过 1 次),因此 x 到 y 的最短路 最多经过 n - 1 次松弛操作(就是更新长度)就应该出现,如果第 n 次松弛还可以得到最优,那么这个图就肯定是存在环了(直接用Dijkstra 就无法得到最优的,环的存在会影响最优解是否存在)。

这里给的顶点时货币的英文名,为了方便简洁,用map 将货币名 与 编号一一对应

此题有多种解法,注意到顶点最大为30(限制很小,不愧是模板练习题),可用Floyd算法求出整个图的最短路,注意此处并不是真正的最短路,但通过插点,即 i -> j 能否改成 i -> k -> j 的路,就会把环给考虑至少一次,那么对应的 path[i][i] 也就是本金肯定是增加的(相对于初值),为了方便,将本金设为 1 .

C++版本一

Bellman_ford

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include<set>
#include<vector>
#include<map>

#define INF 0x3f3f3f3f
using namespace std;
int t,n,m;

map<string ,int> m0;

double r;
double dist[200];

struct node
{
    int a,b;
    double r;
    node(int sst,int eed,double rtt) : a(sst),b(eed),r(rtt) {}
    node() {}

};
vector<node> G;
bool Bellman_ford(int v)
{
    memset(dist,0,sizeof(dist));
    dist[v] = 1;
    for(int j = 1;j < n;j++) {  // n - 1 次松弛操作
        for(int i = 0;i <G.size();i++) {
            int p1 = G[i].a,p2 = G[i].b;
            if(dist[p2] < dist[p1] * G[i].r) { //尝试更新顶点 v 到 p2 的距离
                dist[p2] = dist[p1] * G[i].r;
            }
        }
    }
    for(int i = 0;i < G.size();i++){
        int p1 = G[i].a,p2 = G[i].b;
        if(dist[p2] < dist[p1] * G[i].r) { //第 n 次松弛可以得到更优解,则存在环
            return true;
        }
    }
    return false;
}

int main()
{
    t=0;
    while(~scanf("%d",&n)){
        if(n==0)    break;
        t++;
        char tempchar1[100],tempchar2[100];
        for(int i=0;i<n;i++){
            scanf("%s",tempchar1);
            m0[tempchar1] = i;
        }
        scanf("%d",&m);

        G.clear();
        for(int i=1;i<=m;i++){
            scanf("%s %lf %s",tempchar1,&r,tempchar2);

            G.push_back( node(m0[tempchar1],m0[tempchar2],r) );
        }
        for(int i=0;i<n;i++){
        if(Bellman_ford(i)){
            printf("Case %d: Yes\n",t);
            break;
        }
        else if(i==n-1)
            printf("Case %d: No\n",t);
        }
    }
    //cout << "Hello world!" << endl;
    return 0;
}

C++版本二

Floyd 

//floyed
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
 
using namespace std;
int n,m;
double dist[40][40];
map<string,int> money;
 
void init()
{
    for(int i = 0;i < n;i++) {
        for(int j = 0;j < n;j++){
            if(i == j) dist[i][j] = 1;
            else dist[i][j] = 0;
        }
    }
}
 
void floyd()
{
    for(int k = 0;k < n;k++) {
        for(int i = 0;i < n;i++) {
            for(int j = 0;j < n;j++) {
                if(dist[i][j] < dist[i][k] * dist[k][j])
                    dist[i][j] = dist[i][k] * dist[k][j];
            }
        }
    }
}
 
int main()
{
    int cas = 1;
    string s,ss;
    double r;
    while(~scanf("%d",&n) &&n) {
        init();
        for(int i = 0;i < n;i++) {
            cin >> s;
            money[s] = i;
        }
        cin >> m;
 
        for(int i = 0;i < m;i++) {
            cin >> s >> r >> ss;
            dist[money[s] ][money[ss] ] = r;
        }
        floyd();
        printf("Case %d: ",cas++);
        for(int i = 0;i < n;i++) {
            if(dist[i][i] > 1) {
                cout << "Yes" << endl;
                break;
            }
            else if(i == n - 1)
                cout << "No" <<endl;
        }
    }
    return 0;
}

C++版本三 

Floyd 

#include <iostream>
#include <map>
#include <cstring>
#include <string>
using namespace std;
 
int main()
{
    double e[35][35];
    int n;
    map<string,int>exchange_rate;
int num=0;
    while (cin>>n&&n!=0)
    {
 
 
        memset(e,0,sizeof(e));
        for(int i=1; i<=n; i++)
            e[i][i]=1;
 
        num++;
        int p=1;
        string currency ;
        for(int i=0; i<n; i++)
        {
            cin >>currency;
            exchange_rate.insert(make_pair(currency,p++));  
        }
 
        int m;
        cin >>m;
        for(int i=0; i<m; i++)
        {
            string a,c;
            double b;
            cin >>a>>b>>c;
 
            e[exchange_rate[a]][exchange_rate[c]]=b;
        }
 
        for(int k=1; k<=n; k++)
            for(int i=1; i<=n; i++)
                for(int j=1; j<=n; j++)
                    if(e[i][j]<e[i][k]*e[k][j])
                        e[i][j]=e[i][k]*e[k][j];
        int cis=0;
        for(int i=1; i<=n; i++)
            if(e[i][i]>1)
            {
                cis++;
            }
 
        if(cis==0)
            cout <<"Case "<<num<<": No"<<endl;
        else
            cout <<"Case "<<num<<": Yes"<<endl;
 
            exchange_rate.clear();
 
    }
 
    return 0;
}

C++版本四

SPFA

#include<iostream>
using namespace std;
#include<string.h>
#include<stdio.h>
#include<queue>
#define maxn 0x7fffffff
#include<map>
int n,m,f;
double dis[3000];
int vis[3000],head[3000];
struct node
{
    double w;
    int e,next;
}edge[3000];
void add(int s,int e,double w)
{
    edge[f].e=e;
    edge[f].w=w;
    edge[f].next=head[s];
    head[s]=f++;
}
int spfa(int s)
{
    int cur,k,i;
    queue<int>q;
    while(!q.empty())
    {
        q.pop();
    }
    q.push(s);
    dis[s]=1;
    vis[s]=1;
    while(!q.empty())
    {
        cur=q.front();
        q.pop();
        vis[cur]=0;
        for(i=head[cur];i!=-1;i=edge[i].next)
        {
            k=edge[i].e;
           if(dis[k]<dis[cur]*edge[i].w)
           {
               dis[k]=dis[cur]*edge[i].w;
               if(!vis[k])
               {
                   q.push(k);
                   vis[k]=1;
               }
           }
           if(dis[s]>1)
            return 1;
        }
    }
    return 0;
}
int main()
{
     int i,j=1;
     double w;
     char s[100],s1[100],s2[100];
     map<string,int>v;
     while(cin>>n)
     { if(n==0)break;
         f=0;
         memset(vis,0,sizeof(vis));
         memset(head,-1,sizeof(head));
     for(i=0;i<100;i++)
        dis[i]=0;
     for(i=1;i<=n;i++)
     {
         cin>>s;
         v[s]=i;
     }
      cin>>m;
      for(i=0;i<m;i++)
      {
          cin>>s1>>w>>s2;
          add(v[s1],v[s2],w);
      }
      cout<<"Case "<<j<<": ";
      for(i=1;i<=n;i++)
      {
          if(spfa(i))
         {
            cout<<"Yes\n";
            break;
         }
      }
      if(i==n+1)
      cout<<"No\n";
        j++;
     }
    return 0;
}

 

全部评论

相关推荐

点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
正在热议
更多
# 长得好看会提高面试通过率吗? #
3013次浏览 43人参与
# HR最不可信的一句话是__ #
1003次浏览 32人参与
# 米连集团26产品管培生项目 #
7031次浏览 224人参与
# 春招至今,你的战绩如何? #
14569次浏览 136人参与
# AI面会问哪些问题? #
880次浏览 21人参与
# 你的实习产出是真实的还是包装的? #
2652次浏览 52人参与
# MiniMax求职进展汇总 #
24856次浏览 321人参与
# 沪漂/北漂你觉得哪个更苦? #
1181次浏览 37人参与
# 你做过最难的笔试是哪家公司 #
1106次浏览 20人参与
# AI时代,哪个岗位还有“活路” #
2670次浏览 49人参与
# XX请雇我工作 #
51142次浏览 171人参与
# 军工所铁饭碗 vs 互联网高薪资,你会选谁 #
7960次浏览 43人参与
# 简历第一个项目做什么 #
32057次浏览 357人参与
# 简历中的项目经历要怎么写? #
310884次浏览 4257人参与
# 不考虑薪资和职业,你最想做什么工作呢? #
152809次浏览 888人参与
# 当下环境,你会继续卷互联网,还是看其他行业机会 #
187545次浏览 1123人参与
# AI时代,哪些岗位最容易被淘汰 #
64507次浏览 863人参与
# 如果重来一次你还会读研吗 #
229970次浏览 2011人参与
# 投格力的你,拿到offer了吗? #
178209次浏览 889人参与
# 你怎么看待AI面试 #
180635次浏览 1295人参与
# 正在春招的你,也参与了去年秋招吗? #
364139次浏览 2641人参与
# 腾讯音乐求职进展汇总 #
160814次浏览 1114人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务