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 }

 

posted on 2013-08-14 15:45  随风浪子的博客  阅读(309)  评论(0编辑  收藏  举报

导航