题意:给几个国家,然后给这些国家之间的汇率。判断能否通过这些汇率差进行套利交易。
Floyd的算法可以求出任意两点间的最短路径,最后比较本国与本国的汇率差,如果大于1,则可以。否则不可以。
最短路径,Floyd的算法原理:
Floyd-Warshall算法的原理是动态规划。
设D(i,j,k)为从i到j的只以集合中的k节点为中间节点的最短路径的长度。
若最短路径经过点k,则;D(i,j,k)=D(i,k)+D(k,j)
若最短路径不经过点k,则D(i,j,k)=D(i,j,k-1)。
因此,D(i,j,k)=min{D(i,k)+D(k,j),D(i,j,k-1)}。
在实际算法中,为了节约空间,可以直接在原来空间上进行迭代,这样空间可降至二维。
算法描述:
for k ← 1 to n dofor i ← 1 to n do
for j ← 1 to n do
if (D(i,k)+D(k,j)<D(i,j)) then
D(i,j)← D(i,k)+D(k,j);
首先字符串映射成整形数不是问题,我们可以用map轻松解决。
然后跑一遍类似于fylod算法的程序。最后检查是否有Map[i][i]>1即可。
AC代码如下
#include<iostream>
#include<map>
using namespace std;
const int maxn=105,inf=1<<29;
int n,m;
double Map[maxn][maxn];
void floyd()
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(Map[i][j]<Map[i][k]*Map[k][j]) Map[i][j]=Map[i][k]*Map[k][j];
}
int main()
{
string s;
int Case=1;
while(cin>>n,n)
{
fill(&Map[0][0],&Map[maxn][0],0);
map<string,int>mp;
for(int i=1;i<=n;i++)
{
cin>>s;
mp[s]=i;
}
cin>>m;
for(int i=1;i<=m;i++)
{
string a,b;
double w;
cin>>a>>w>>b;
Map[mp[a]][mp[b]]=w;
}
floyd();
double Max=0;
for(int i=1;i<=n;i++)
Max=max(Map[i][i],Max);
cout<<"Case "<<Case++<<": ";
if(Max>1) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}