用map建立从货币名称到序号的映射,看做节点,汇率则看做边权,是单向路。
用floyd,只不过这里把加号变成乘号,而且是两点间的最大值。 最后求是否有这么一点,从该点出发,再回到该点,总的值大于1。
注意: 不能使用dijaskra,因为增值的方法不一定是优先选择权值最大的路径,有可能是一开始的汇率小,但之后就大,总的乘积大于1.
所以要用以动态规划为基本思想的floyd来做。
#include <iostream> #include <algorithm> #include <string.h> #include <string> #include <cstring> #include <stdio.h> #include <map> #include <vector> using namespace std; map<string, int> currency; //建立从货币名称到编号的映射 double rate[1010][1010];//rate[i][j]表示i兑换j货币的汇率 vector<int> link[40];//link[i]表示i可以与哪些货币兑换 int n,m,start; double r; char str1[101],str2[101]; int cases=0; int main() { while(scanf("%d",&n)!=EOF){ if(n==0) break; cases++; bool flag=false; for(int i=0;i<=n;i++) link[i].clear(); currency.clear(); memset(rate,0,sizeof(rate)); //memset(dis,maxn,sizeof(dis)); for(int i=1;i<=n;i++){ scanf("%s",str1); currency[str1]=i; } scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%s%lf%s",str1,&r,str2); int a=currency[str1]; int b=currency[str2]; rate[a][b]=r; link[a].push_back(b); } //floyd算法 for(int k=1;k<=n;k++){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ //尽可能使rate[i][j]大 if(rate[i][k]*rate[k][j]>rate[i][j]){ rate[i][j]=rate[i][k]*rate[k][j]; } } } } for(int i=1;i<=n;i++){ if(rate[i][i]>1){ flag=true; break; } } if(flag){ printf("Case %d: Yes ",cases); } else{ printf("Case %d: No ",cases); } } return 0; }