POJ 2240 Arbitrage(Floyed-Warshall算法)

题意:给出n种货币,m种兑换比率(一种货币兑换为另一种货币的比率),判断测试用例中套汇是否可行。(套汇的意思就是在经过一系列的货币兑换之后,是否可以获利。例如:货币i→货币j→货币i,这样兑换后,是否可以获利,即比率是否>1)。举个例子理解套汇:假设,1美元买10人民币(比率为10),10人民币买100美元(比率为10)。这就是套汇,总比率=10*10=100,100>1,所以可以获利。

思路:Floyed-Warshall算法,枚举所有的货币之间的兑换比率,最后若存在一种回路且回路比率>1的话,则套汇可行。

课本代码:

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

const int maxn=50;//货币种类上限	
const int maxl=1005;//货币名字长度上限

char str[maxn][maxl],stra[maxl],strb[maxl];//货币种类数组str,源货币stra,目标货币strb。

long double dist[maxn][maxn];//比率矩阵

int n,m;

int find(char *_str){//查找货币的序号i
	for(int i=1;i<=n;i++)
		if(strlen(_str)==strlen(str[i])&&strcmp(_str,str[i])==0) return i;
		return 0;
}

int main(){
	while(scanf("%d",&n)&&n){
		static int cnt=0;
		int i,j,k;
		for(i=1;i<=n;i++)//初始化货币比率
			for(j=1;j<=n;j++)
				dist[i][j]=0;
			for(i=1;i<=n;i++)//0不用,作为未知货币。
				scanf("%s",str[i]);
			scanf("%d",&m);
			for(i=1;i<=m;i++){
				double w;
				scanf("%s %lf %s",stra,&w,strb);
				dist[find(stra)][find(strb)]=w;
			}
			for(k=1;k<=n;k++)//枚举中间节点k		
				for(i=1;i<=n;i++)//枚举互不相同的节点对(i,j)
					for(j=1;j<=n;j++)
						if(i!=j&&j!=k&&k!=i)
							if(dist[i][k]*dist[k][j]>dist[i][j])
								dist[i][j]=dist[i][k]*dist[k][j];
			bool flag=0;//标志初始化
			for(i=1;i<=n;i++)//枚举每种货币
				for(j=1;j<=n;j++)//枚举中间货币
					if(dist[i][j]*dist[j][i]>1)//如果比率>1,则套汇可行
						flag=1;
			printf("Case %d: %s
",++cnt,flag?"Yes":"No");
	}
	return 0;
}



原文地址:https://www.cnblogs.com/gongpixin/p/4477407.html