poj1860——Currency Exchange

题目大意:有n种货币,给出m种兑换方式,问nick能不能用手中的S型货币,经过一系列兑换后赚钱

输入:n  m  s  s型货币的个数V(1<=s<=n<=100, 1<=m<=100, 0<=V<=103

           a  b  Rab  Cab  Rba  Cba(共m行 a b两种货币的兑换汇率以及手续费)

输出:YES/NO

分析:用bellman-ford算法(讲解详见http://blog.sina.com.cn/s/blog_7058524b0101a8gu.html)变相求最大路径,和poj2240(多源)很像。用这个算法的原因是这种货币兑换问题是存在负权路的,所以不能用Dijkstra等算法来做,否则会出现某一大路径加一负值路径小于小路径的情况,求不出最终结果,而bellman算法是可以判断带负权权值的图中是否存在负权回路的,当松弛n次时还能继续变大说明存在正环(本题其实就是判断是否有正环)。

           还可以用spfa算法(队列优化的最短路径算法),就是效率更高的bellman算法。

代码:转载自http://blog.youkuaiyun.com/lyhvoyage/article/details/19281013

方法一:bellman-ford算法。

  1. #include<stdio.h>  
  2. #include<string.h>  
  3. int n, m, s, C;  
  4. double v, dis[110];  
  5. struct point  
  6. {  
  7.     int a, b;  
  8.     double rate, cost;  
  9. }p[500];  
  10.   
  11. bool Bellman_Ford()  
  12. {  
  13.     memset(dis, 0, sizeof(dis));  //此处与Bellman-Ford的处理相反,初始化为源点到各点距离0,到自身的值为原值  
  14.     dis[s] = v;  
  15.     for(int i = 1; i <= n - 1; i++)  
  16.     {  
  17.         bool flag = false;  
  18.         for(int j = 0; j < C; j++)  
  19.         {  
  20.             int a = p[j].a, b = p[j].b;  
  21.             double r = p[j].rate, c = p[j].cost;  
  22.             if(dis[b] < (dis[a] - c) * r)  
  23.             {  
  24.                  dis[b] = (dis[a] - c) * r;  
  25.                  flag = true;  
  26.             }  
  27.   
  28.         }  
  29.         if(!flag)  
  30.             break;  
  31.     }  
  32.     for(int i = 0; i < C; i++)  
  33.         if(dis[p[i].b] < (dis[p[i].a] - p[i].cost) * p[i].rate)    //正环能够无限松弛  
  34.             return true;  
  35.     return false;  
  36. }  
  37.   
  38. int main()  
  39. {  
  40.     int i, j, a, b;  
  41.     double rab, rba, cab, cba;  
  42.     while(~scanf("%d%d%d%lf",&n,&m,&s,&v))  
  43.     {  
  44.         C = 0;  
  45.         for(i = 0; i < m; i++)  
  46.         {  
  47.             scanf("%d%d%lf%lf%lf%lf",&a, &b, &rab, &cab, &rba, &cba);  
  48.             p[C].a = a;  
  49.             p[C].b = b;  
  50.             p[C].rate = rab;  
  51.             p[C++].cost = cab;  
  52.             p[C].a = b;  
  53.             p[C].b = a;  
  54.             p[C].rate = rba;  
  55.             p[C++].cost = cba;  
  56.         }  
  57.         if(Bellman_Ford())  
  58.             printf("YES\n");  
  59.         else  
  60.             printf("NO\n");  
  61.     }  
  62.     return 0;  
  63. }
方法二:spfa算法。

  1. #include<stdio.h>  
  2. #include<string.h>  
  3. #include<queue>  
  4. using namespace std;  
  5. const int N = 110;  
  6. int n, m, s;  
  7. double dis[N], v, rate[N][N], cost[N][N];  
  8.   
  9. bool spfa(int start)  
  10. {  
  11.     bool inq[110];  
  12.     memset(inq, 0, sizeof(inq));  
  13.     memset(dis, 0, sizeof(dis));  
  14.     dis[start] = v;  
  15.     queue<int> Q;  
  16.     Q.push(start);  
  17.     inq[start] = true;  
  18.     while(!Q.empty())  
  19.     {  
  20.         int x = Q.front();  
  21.         Q.pop();  
  22.         inq[x] = false;  
  23.         for(int i = 0; i <= n; i++)  //这里试一试能不能将0改成1
  24.         {  
  25.             if(dis[i] < (dis[x] - cost[x][i]) * rate[x][i])  
  26.             {  
  27.                 dis[i] = (dis[x] - cost[x][i]) * rate[x][i];  
  28.                 if(dis[start] > v)  
  29.                     return true;  
  30.                 if(!inq[i])  
  31.                 {  
  32.                     Q.push(i);  
  33.                     inq[i] = true;  
  34.                 }  
  35.             }  
  36.         }  
  37.     }  
  38.     return false;  
  39. }  
  40.   
  41. int main()  
  42. {  
  43.     int i, j;  
  44.     while(~scanf("%d%d%d%lf",&n,&m,&s,&v))  
  45.     {  
  46.         int a, b;  
  47.         double rab, rba, cab, cba;  
  48.         for(i = 1; i <= n; i++)  
  49.             for(j = 1; j <= n; j++)  
  50.             {  
  51.                 if(i == j)  
  52.                     rate[i][j] = 1;  
  53.                 else  
  54.                     rate[i][j] = 0;  
  55.                 cost[i][j] = 0;  
  56.             }  
  57.         for(i = 0; i < m; i++)  
  58.         {  
  59.             scanf("%d%d%lf%lf%lf%lf",&a,&b,&rab,&cab,&rba,&cba);  
  60.             rate[a][b] = rab;  
  61.             rate[b][a] = rba;  
  62.             cost[a][b] = cab;  
  63.             cost[b][a] = cba;  
  64.         }  
  65.         if(spfa(s))  
  66.             printf("YES\n");  
  67.         else  
  68.             printf("NO\n");  
  69.     }  
  70.     return 0;  
  71. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值