Arbitrage
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6465 Accepted Submission(s): 2985
Problem Description
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
标题大意:套汇
题目大意:套汇,给你一些个货币名称,给你一堆货币之间兑换的汇率,问你有没有哪种货币能够在多次(当然1次是不行的)交换货币的情况下,使得原来的货币增多。题干中就举出一个例子,从1个US货币在几次交换之后变成了1.05个货币。如果能够使得货币增加,输出yes,否则输出no。
思路:对于每种货币的交换值我们当做边权值。那么不难理解:如果i货币能够换到j货币,j货币能够换到k货币,那么i货币就能换到k货币,换得的值为:w【i】【j】*w【j】【k】。如果w【i】【k】没有直接交换的汇率,那么w【i】【k】的汇率就暂时赋值为w【i】【j】*w【j】【k】,如果w【i】【k】之间有汇率,那么:
w【i】【k】=max(w【i】【j】*w【j】【k】,w【i】【k】),整个dp的过程我们使用floyd算法来实现。毕竟n的范围才30,完全不用担心超时的问题。
而且我们这样来解决这个问题,最终得到的w【】【】,直接遍历询问w【i】【i】是否大于1即可。因为floyd可以解决有向环的问题啊!~~~~~~~··
AC代码:
#include<stdio.h>
#include<string.h>
#include<vector>
#include<iostream>
#include<map>
using namespace std;
double w[60][60];
char tmp[1000],tmp2[1000];
double change;
int n;
double max(double a,double b)
{
return a>b?a:b;
}
void init()
{
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
w[i][j]=0x1f1f1f1f;
}
}
}
int main()
{
int kase=0;
while(~scanf("%d",&n))
{
if(n==0)break;
init();
int cont=1;
map<string, int >mp;
for(int i=0; i<n; i++)
{
scanf("%s",tmp);
mp[tmp]=cont++;
}
int q;
scanf("%d",&q);
while(q--)
{
scanf("%s%lf%s",tmp,&change,tmp2);
w[mp[tmp]][mp[tmp2]]=min(w[mp[tmp]][mp[tmp2]],change);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
if(w[j][i]<0x1f1f1f1f&&w[i][k]<0x1f1f1f1f)
{
if(w[j][k]==0x1f1f1f1f)w[j][k]=w[j][i]*w[i][k];
else w[j][k]=max(w[j][i]*w[i][k],w[j][k]);
}
}
}
}
int flag=0;
for(int i=1;i<=n;i++)
{
if(w[i][i]>1)flag=1;
}
if(flag==1)
{
printf("Case %d: Yes\n",++kase);
}
else printf("Case %d: No\n",++kase);
}
}