POJ_1860_Currency Exchange(最短路径算法)
/*
http://poj.org/problem?id=1860
题意:有好几种货币可以进行交换,给出Nick所拥有的货币数,让你计算
能不能通过货币的交换而升值,升值输出YES。否则输出NO;
3 2 1 20.0;分别指一共有几种货币类型 有几种货币可以交换 Nick所拥有的是哪一种货币 货币量;
1 2 1.00 1.00 1.00 1.00;分别指
货币1 2之间的利息是1.00汇率是1.00;
货币2 1之间的利息是1.00汇率是1.00;
货币的计算方式是(本金-手续费)*汇率;
解题思路:用图来存储信息,每个结点代表一种货币,此货币与另一货币的交换信息
就是有向边,用含有四个成员的结构体进行存储,u,v是边的起点和终点
人,r,c是汇率及手续费。这样问题就转化成有没有那么一个回路使得钱数十是一直增加的
如果有,那么不管是哪个回路都能附带着使V(初始钱数)增加。
具体解释见代码,可结合网上的一个图。
*/
1 # include <stdio.h> 2 # include <string.h> 3 double d[500];//存储结点的钱数,即当前货币的钱数。 4 struct node 5 { 6 int u,v; //边的起点和终点。 7 double r,c; 8 }ed[500]; //存储边点信息。 9 int N,M,S,leag; 10 double V; 11 int bellman() 12 { 13 memset(d,0,sizeof(d)); 14 d[S]=V; // initial当前钱数。 15 while(d[S]<=V)//只要遍历过程出现d[S]>V说明货币可以增值,退出。 16 { 17 int flag=0; 18 for(int i=0;i<leag;i++) 19 { 20 //如果终点的钱数小于起点经过换算后的钱数那么修改重点的钱数值。 21 if(d[ed[i].v] < (d[ed[i].u]-ed[i].c)*ed[i].r) 22 { 23 d[ed[i].v]=(d[ed[i].u]-ed[i].c)*ed[i].r; //注意不能相加。 24 flag=1; 25 } 26 } 27 if(!flag)//全部遍历过后没有正权回路,那么判断一次退出。 28 return d[S]>V ? 1:0; 29 } 30 return 1; 31 32 } 33 int main() 34 { 35 int i,j,aa,bb; 36 double rab,cab,rba,cba; 37 scanf("%d%d%d%lf",&N,&M,&S,&V); 38 leag=0; 39 for(i=0;i<M;i++) 40 { 41 scanf("%d%d%lf%lf%lf%lf",&aa,&bb,&rab,&cab,&rba,&cba); 42 ed[leag].u=aa; ed[leag].v=bb; 43 ed[leag].r=rab; ed[leag].c=cab; 44 leag++; 45 ed[leag].u=bb; ed[leag].v=aa; 46 ed[leag].r=rba; ed[leag].c=cba; 47 leag++; 48 } 49 if(bellman() == 1) 50 printf("YES\n"); 51 else 52 printf("NO\n"); 53 return 0; 54 }