HDOJ-1217-Arbitrage 解题报告

       求最短路的题,与普通最短路不同的地方是运算是用乘法而不是加法。题意:套汇是指利用不同外汇市场的外汇差价,在某一外汇市场上买进某种货币,同时在另一外汇市场上卖出该种货币,以赚取利润。这种利润称之为套利。比如1美元可以买0.5英镑,而1英镑可以买10法郎,2法郎可以买1美元,那么可用通过套汇使用1美元买到2.5美元,套利是存在的。下面给出各个货币的种类和名称,再给出一些货币转换的汇率,请问是否存在套利?


       解题思路:因为汇率的转换是使用乘法,而与小于1的数相乘是会导致原来的数变小的,所以此题相当于是有负权的题目,很明显Dijkstra算法是不能使用的了。题目问套利是否存在,因此每种货币是否存在套利都应该考虑,货币种类不超过30,使用Floyd算法的耗时不会太多。再想想,题目中不一定给出的任意两种货币都能够互相转换,那么不能够转换的话我们如何表示它们之间的汇率呢?用0表示,这样则说明不能够转换。使用Floyd算法求每两种货币能够互相转换的最大汇率,那么最后我们判断每种货币转换为自己时的汇率是否大于1,是的话说明存在套利,否的话则说明本货币不存在套利。注意本题是单向图。


       接下来是我的解题代码:Floyd解法

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 31
#define Max(a, b) (a > b ? a : b)

int n, m;
double map[N][N];   //存储汇率
char str[N][N];     //存储货币名称

void Init();

void Read();

int Count(char s[]);   //计算字符串编号

int Floyd();

int main()
{
    int t = 1;
    while (~scanf("%d", &n))
    {
        Init();
        if (n == 0) break;
        Read();
        printf("Case %d: ", t++);
        if (Floyd() == 1)
        {
            puts("Yes");
        }
        else
        {
            puts("No");
        }
    }
    return 0;
}

void Init()
{
    int i, j;
    for (i=0; i<N; ++i)
    {
        for (j=0; j<N; ++j)
        {
            map[i][j] = 0;      //0则代表不能转换
        }
    }
    return;
}

void Read()
{
    int i;
    char sa[N], sb[N];
    double x;
    for (i=0; i<n; ++i)
    {
        scanf("%s", str[i]);
    }
    scanf("%d", &m);
    for (i=0; i<m; ++i)
    {
        scanf("%s %lf %s", sa, &x, sb);
        map[Count(sa)][Count(sb)] = x;
    }
    return;
}

int Count(char s[])     //计算字符串编号
{
    int i;
    for (i=0; i<n; ++i)
    {
        if (strcmp(s, str[i]) == 0)
        {
            return i;
        }
    }
    return -1;
}

int Floyd()
{
    int i, j, k;
    for (k=0; k<n; ++k)
    {
        for (i=0; i<n; ++i)
        {
            for (j=0; j<n; ++j)
            {
                map[i][j] = Max(map[i][j], map[i][k] * map[k][j]);
            }
        }
    }
    for (j=0; j<n; ++j)     //检验判断是否存在套利
    {
        if (map[j][j] > 1)
        {
            return 1;
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值