算法导论--学习笔记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;
}
例如,假定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;
}
相关文章推荐
- 算法导论学习笔记-第十二章-二叉查找树
- 算法导论学习笔记(1,2)
- 算法导论第二章学习笔记
- 插入排序算法学习——算法导论学习笔记
- 算法导论分而治之学习笔记
- 算法导论第五章学习笔记
- 算法导论学习笔记-2
- 算法导论第二章学习笔记
- 算法导论学习笔记——快速排序算法
- 算法导论学习笔记-第8章 线性时间排序
- 算法导论学习笔记-第七章-快速排序
- 算法导论学习笔记-第十七章-平摊分析
- 算法导论学习笔记-第十五章-动态规划
- 算法导论学习笔记-第9章 中位数和顺序统计学
- 算法导论学习笔记-第7章 快速排序
- 算法导论学习笔记-第四章-递归式
- 算法导论学习笔记-第3章 函数的增长
- 算法导论学习笔记(一)
- 算法导论学习笔记——合并排序
- 算法导论第四章学习笔记