您的位置:首页 > 其它

算法导论--学习笔记019

2014-12-03 14:37 225 查看
1.套汇是指利用货币汇兑率的差异将一个单位的某种货币转换为大于一个单位的同种货币的方法。
例如,假定1美元可以买0.7英镑,1英镑可以买9.5法郎,1法郎可以买到0.16美元。通过货币兑换,一个商人可以从1美元开始买入,得到0.7*9.5*0.16=1.064美元,从而获得6.4%的利润。

假定已知n种货币1c,2c,„,nc和有关兑换率的n*n的表R。其中,R[i,j]是一个单位货币ic可以买到的货币jc的单位数。
(1)试设计一个有效算法,用以确定是否存在一个货币序列1ic,2ic,„,ikc使得R[i1,i2]R[i2,i3]„R[ik,i1] >1 并分析算法的计算时间。
(2)试设计一个算法打印出满足本题(1)中条件的所有序列,并分析算法的计算时间。

二、算法问题
形式化表示此问题可转化为图问题。构造一个图G=(V,E),其中顶点为ci,任意两点间都有两条有向边(vi, vj), (vj, vi)。则有|V| = n, |E| = n(n-1)/2。从题目条件可得:因此可设边(ci1,ci2) 权值为-lgR[i1, i2],这样问题转化为在图中寻找负权回路的问题。可以现在图中添加一个新的顶点s, s指向所有入度为0的顶点,权值为0;然后以s为起点运行Bellman-Ford算法,即可确定是否有负权回路。

-----------------------------------------------我是分割线----------------------------------------------------------
为了防止非法套汇:
汇率兑换矩阵R=(rij)n*n是正反矩阵:

rii=1;(i=0,1,2,3,4.......);
rij=1/rji;
rij=rik/rjk
具有唯一非零的最大特征值。Xmax=n;

------------------------------------我是分割线------------------------------------------------------

[cpp]
view plaincopy

#include <iostream>  
#include <cstdio>  
#include <algorithm>  
#include <cstring>  
using namespace std;  
  
const int N = 35;  
const int E = 905;  
const double MAX = 999999999;  
  
struct Edge  
{  
    int beg;  
    int end;  
    double rate;  
}edge[E];  
double mindis
;  
int n, e;  
struct Name  
{  
    char str[55];  
}cname
;  
  
bool cmp(const Name& n1, const Name& n2)  
{  
    return strcmp(n1.str, n2.str) < 0;  
}  
  
int bisearch(char* str)  
{  
    int low = 0, high = n - 1, mid;  
    int t;  
    while (low <= high)  
    {  
        mid = (low + high) >> 1;  
        t = strcmp(str, cname[mid].str);  
        if (t == 0) return mid;  
        else if (t < 0) high = mid - 1;  
        else low = mid + 1;  
    }  
    return -1;  
}  
  
bool relax(int pe)  
{  
    if (mindis[edge[pe].beg] * edge[pe].rate > mindis[edge[pe].end])   
    {  
        mindis[edge[pe].end] = mindis[edge[pe].beg] * edge[pe].rate;  
        return true;  
    }  
    return false;  
}  
  
bool bellman_ford()  
{  
    bool flag;  
    for (int i = 0; i < n; ++i) mindis[i] = 1.0;  
    for (int i = 0; i < n - 1; ++i)  
    {  
        flag = false;  
        for (int j = 0; j < e; ++j)  
        {  
            if (relax(j)) flag = true;  
        }  
        if (!flag) return false;  
    }  
    for (int i = 0; i < e; ++i)  
    {  
        if (relax(i)) return true;  
    }  
    return false;  
}  
  
int main()  
{  
    char sbeg[55], send[55];  
    double rate;  
    int T = 1;  
    while (scanf("%d", &n) != EOF && n)  
    {  
        for (int i = 0; i < n; ++i) scanf("%s", cname[i].str);  
        sort(cname, cname + n, cmp);  
        scanf("%d", &e);  
        for (int i = 0; i < e; ++i)  
        {  
            scanf("%s%lf%s", sbeg, &rate, send);  
            edge[i].beg = bisearch(sbeg);  
            edge[i].end = bisearch(send);  
            edge[i].rate = rate;  
        }  
        printf("Case %d: ", T++);  
        if (bellman_ford()) printf("Yes\n");  
        else printf("No\n");  
    }  
    return 0;  
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: