zoukankan      html  css  js  c++  java
  • POJ1860Currency Exchange

    转载请注明出处:優YoU  http://user.qzone.qq.com/289065406/blog/1299337940

     

    提示:关键在于反向利用Bellman-Ford算法

    题目大意

    有多种汇币,汇币之间可以交换,这需要手续费,当你用100A币交换B币时,AB的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。问s币的金额经过交换最终得到的s币金额数能否增加

    货币的交换是可以重复多次的,所以我们需要找出是否存在正权回路,且最后得到的s金额是增加的

    怎么找正权回路呢?(正权回路:在这一回路上,顶点的权值能不断增加即能一直进行松弛)

     

     

    题目分析:

    一种货币就是图上的一个点

    一个“兑换点”就是图上两种货币之间的一个兑换环,相当于“兑换方式”M的个数,是双边

    唯一值得注意的是权值,当拥有货币A的数量为V时,AA的权值为K,即没有兑换

    AB的权值为(V-Cab)*Rab

    本题是“求最大路径”,之所以被归类为“求最小路径”是因为本题题恰恰与bellman-Ford算法的松弛条件相反,求的是能无限松弛的最大正权路径,但是依然能够利用bellman-Ford的思想去解题。

    因此初始化d(S)=V   而源点到其他店的距离(权值)初始化为无穷小(0),当s到其他某点的距离能不断变大时,说明存在最大路径

     

     1 //Memory Time 
    2 //252K 16MS
    3
    4 #include<iostream>
    5 using namespace std;
    6
    7 int n; //货币种数
    8 int m; //兑换点数量
    9 int s; //持有第s种货币
    10 double v; //持有的s货币的本金
    11
    12 int all; //边总数
    13 double dis[101]; //s到各点的权值
    14
    15 class exchange_points
    16 {
    17 public:
    18 int a; //货币a
    19 int b; //货币b
    20 double r; //rate
    21 double c; //手续费
    22 }exc[202];
    23
    24 bool bellman(void)
    25 {
    26 memset(dis,0,sizeof(dis)); //这里与bellman的目的刚好相反。初始化为源点到各点距离无穷小
    27 dis[s]=v; //即bellman本用于找负环,求最小路径,本题是利用同样的思想找正环,求最大路径
    28
    29 /*relax*/
    30
    31 bool flag;
    32 for(int i=1;i<=n-1;i++)
    33 {
    34 flag=false;
    35 for(int j=0;j<all;j++)
    36 if(dis[exc[j].b] < (dis[exc[j].a] - exc[j].c) * exc[j].r) //寻找最长路径
    37 { //进行比较的是"某点到自身的权值"和"某点到另一点的权值"
    38 dis[exc[j].b] = (dis[exc[j].a] - exc[j].c) * exc[j].r;
    39 flag=true;
    40 }
    41 if(!flag)
    42 break;
    43 }
    44
    45 /*Search Positive Circle*/
    46
    47 for(int k=0;k<all;k++)
    48 if(dis[exc[k].b] < (dis[exc[k].a] - exc[k].c) * exc[k].r) //正环能够无限松弛
    49 return true;
    50
    51 return false;
    52 }
    53
    54 int main(void)
    55 {
    56 int a,b;
    57 double rab,cab,rba,cba; //临时变量
    58
    59 while(cin>>n>>m>>s>>v)
    60 {
    61 all=0; //注意初始化
    62 for(int i=0;i<m;i++)
    63 {
    64 cin>>a>>b>>rab>>cab>>rba>>cba;
    65 exc[all].a=a;
    66 exc[all].b=b;
    67 exc[all].r=rab;
    68 exc[all++].c=cab;
    69 exc[all].a=b;
    70 exc[all].b=a;
    71 exc[all].r=rba;
    72 exc[all++].c=cba;
    73 }
    74
    75 /*Bellman-form Algorithm*/
    76
    77 if(bellman())
    78 cout<<"YES"<<endl;
    79 else
    80 cout<<"NO"<<endl;
    81 }
    82
    83 return 0;
    84 }
  • 相关阅读:
    leetcode刷题四<寻找两个有序数组的中位数>
    leetcode刷题第三天<无重复字符的最长子串>
    leetcode刷题第二天<两数相加>
    leetcode刷题第一日<两数和问题>
    sqlalchemy.exc.ProgrammingError: (pymysql.err.ProgrammingError)
    flask微电影系统开发中上下文处理器
    gdb解决字符串打印果断措施
    邻接表
    Jarvis OJ 一些简单的re刷题记录和脚本
    windows控件理论学习
  • 原文地址:https://www.cnblogs.com/lyy289065406/p/2121595.html
Copyright © 2011-2022 走看看