仲裁 POJ - 2240
套利是利用货币汇率的差异将一个单位的货币转换为多个单位的同种货币。例如,假设1美元买0.5英镑,1英镑买10.0法郎,1法郎买0.21美元。然后,通过转换货币,聪明的交易者可以从 1 美元开始,买入 0.5 * 10.0 * 0.21 = 1.05 美元,赚取 5% 的利润。
您的工作是编写一个程序,该程序将货币汇率列表作为输入,然后确定是否可以进行套利。
输入
输入将包含一个或多个测试用例。在每个测试用例的第一行有一个整数 n (1<=n<=30),代表不同货币的数量。接下来的 n 行每行包含一种货币的名称。在名称中不会出现空格。下一行包含一个整数 m,表示要遵循的表格的长度。最后 m 行每行包含源货币的名称 ci、代表从 ci 到 cj 的汇率的实数 rij 和目标货币的名称 cj。没有出现在表中的交换是不可能的。
测试用例之间由一个空行分隔。输入以 n 的零 (0) 值终止。
输出
对于每个测试用例,分别以“Case case: Yes”和“Case case: No”格式打印一行,说明是否可以进行套利。
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
思路:每种钱看成一个点,要获利,就是需要正环,(dis全为0,起点初始值要大,dis每次取大的,一个点进队超n次则,就是有环),map把每个货币的字符串转化为一个记号,方便我们存下来运算。
#include<iostream>
#include<cstring>
#include<map>
#include<queue>
using namespace std;
const int N=100;
int n,m;
int vist[N],head[N],book[N],cnt;
double dis[N];
struct Edge{
int to;
double w;
int next;
}edge[N*N];
void into()
{
memset(vist,0,sizeof(vist));
memset(head,-1,sizeof(head));
memset(book,0,sizeof(book));
fill(dis,dis+N,0);
cnt=0;
}
void add_edge(int u,int v,double w)
{
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
bool SPFA()
{
queue<int> q;
q.push(1);
vist[1]=1;
book[1]++;
dis[1]=1000;
while(!q.empty()){
int cur=q.front();
q.pop();
vist[cur]=0;
for(int i=head[cur];~i;i=edge[i].next){
int next=edge[i].to;
if(dis[next]<dis[cur]*edge[i].w){
dis[next]=dis[cur]*edge[i].w;
if(!vist[next]){
q.push(next);
vist[next]=1;
book[next]++;
if(book[next]>=n) return true;
}
}
}
}
return false;
}
int main()
{
ios::sync_with_stdio(false);
int i,j,time=0;
double w;
string s1,s2;
while(cin>>n&&n){
into();
map<string,int> mp;
for(i=1;i<=n;i++){
cin>>s1;
mp[s1]=i;
}
cin>>m;
for(i=1;i<=m;i++){
cin>>s1>>w>>s2;
add_edge(mp[s1],mp[s2],w);
}
time++;
cout<<"Case "<<time<<":";
if(SPFA()){
cout<<" Yes"<<endl;
}
else cout<<" No"<<endl;
}
}
floyd
#include<iostream>
#include<cstring>
#include<map>
using namespace std;
int n,m;
double e[50][50];
bool floyd()
{
int i,j,k;
for(k=1;k<=n;k++){
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
e[i][j]=max(e[i][j],e[i][k]*e[k][j]);//注意每次取最大的
}
}
}
for(i=1;i<=n;i++){
if(e[i][i]>1.0) return true;//跑一次后,汇率增加,所以就是有正环。
}
return false;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int i,j,k,time=0;
double x;
while(cin>>n&&n){
map<string,int> mp;
string s,s1,s2;
for(i=1;i<=n;i++){
cin>>s;
mp[s]=i;
e[i][i]=1;//初始自己到自己为1,即汇率不变
}
cin>>m;
for(i=1;i<=m;i++){
cin>>s1>>x>>s2;
e[mp[s1]][mp[s2]]=x;
}
time++;
cout<<"Case "<<time<<":";
if(floyd()){
cout<<" Yes"<<endl;
}
else cout<<" No"<<endl;
}
}