poj 1860 -- Currency Exchange(Bellman-Ford)
poj 1860 -- Currency Exchange(Bellman-Ford)
题意:
我们的城市有几个货币兑换点。让我们假设每一个点都只能兑换专门的两种货币。可以有几个点,专门从事相同货币兑换。每个点都有自己的汇率,外汇汇率的A到B是B的数量你1A。同时各交换点有一些佣金,你要为你的交换操作的总和。在来源货币中总是收取佣金。
例如,如果你想换100美元到俄罗斯卢布兑换点,那里的汇率是29.75,而佣金是0.39,你会得到(100 - 0.39)×29.75=2963.3975卢布。
你肯定知道在我们的城市里你可以处理不同的货币。让每一种货币都用唯一的一个小于N的整数表示。然后每个交换点,可以用6个整数表描述:整数a和b表示两种货币,a到b的汇率,a到b的佣金,b到a的汇率,b到a的佣金。
nick有一些钱在货币S,他希望能通过一些操作(在不同的兑换点兑换),增加他的资本。当然,他想在最后手中的钱仍然是S。帮他解答这个难题,看他能不能完成这个愿望。
输入数据:
第一行四个数,N,表示货币的总数;M,兑换点的数目;S,nick手上的钱的类型;V,nick手上的钱的数目;1<=S<=N<=100, 1<=M<=100, V 是一个实数 0<=V<=103.
接下来M行,每行六个数,整数a和b表示两种货币,a到b的汇率,a到b的佣金,b到a的汇率,b到a的佣金(0<=佣金<=102,10-2<=汇率<=102)
输出数据:
如果nick能够实现他的愿望,则输出YES,否则输出NO。
样例输入:
3 2 1 20.0
1 2 1.00 1.00 1.00 1.00
2 3 1.10 1.00 1.10 1.00
样例输出
YES
解题思路:
使用Bellman-Ford,与这道题相似的题POJ 2240 -- Arbitrage(Bellman-Ford)
循环一圈之后就与本金比是否增大是不可取的,因为万一转为本金的佣金很高,但是存在一个一次增加一点点的正环的话就需要循环很多次才可以高于本金。
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 const int maxm = 105;// 1<=S<=N<=100, 1<=M<=100, V is real number, 0<=V<=103. 5 struct node{ 6 int ci,cj;//交换点交换的两种货币 7 double cij;//汇率 i->j 8 double mij; //手续费 9 }state[2*maxm]; 10 int n,m;//n为货币种类数,m为站点数 11 int type;//Nick手上的货币种类 12 double qua;//Nick手上货币的价值 13 bool flag; 14 double dist[maxm]; 15 16 bool solve_case(int v0) 17 { 18 flag = false; 19 memset(dist,0,sizeof(dist)); 20 dist[v0] = qua; 21 for(int k=1;k<=n;k++)//进行n次 松弛操作 22 { 23 flag = false; 24 for(int i=0;i<2*m;i++){//判断每一条有向边,加入它是否能使得最大距离增加 25 if((dist[state[i].ci]-state[i].mij)*state[i].cij > dist[state[i].cj]) 26 { 27 dist[state[i].cj] = (dist[state[i].ci]-state[i].mij)*state[i].cij; 28 flag = true; 29 } 30 } 31 if(!flag)//已经不再进行松弛 32 break; 33 } 34 //循环一圈之后就与本金比是否增大是不可取的,因为万一转为本金的佣金很高, 35 //但是存在一个一次增加一点点的正环的话就需要循环很多次才可以高于本金。 36 //if(dist[v0]>qua) flag = true; 37 38 for(int k=0;k<2*m;k++) 39 if(dist[state[k].cj] < (dist[state[k].ci]-state[k].mij)*state[k].cij ) 40 return true; 41 return false; 42 43 } 44 45 int cin_case() 46 { 47 while(cin>>n){ 48 cin>>m; 49 cin>>type>>qua; 50 for(int i=0;i<2*m;i+=2){//输入交换点的信息 51 cin>>state[i].ci>>state[i].cj>>state[i].cij>>state[i].mij>>state[i+1].cij>>state[i+1].mij; 52 state[i+1].cj = state[i].ci;state[i+1].ci = state[i].cj; 53 } 54 return 1; 55 } 56 return 0; 57 } 58 59 int main() 60 { 61 while(cin_case()) 62 { 63 if(solve_case(type)) cout<<"YES"<<endl; 64 else cout<<"NO"<<endl; 65 } 66 67 return 0; 68 }