POJ 1860

本文介绍了一种利用Bellman-Ford算法解决货币兑换问题的方法,通过构建图模型来判断是否存在可以使财富无限增长的兑换路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import java.util.Scanner;

public class Main
{
       private int n;   //全部有多少种货币
       private int m;   //有多少兑换方法
       private Currency[] currencies;
       private double[] dis;         //解出到了第i种货币时,对应的货币值
       private class Currency
       {
               public int s1;        //货币1
               public int s2;        //货币2
               public double r;     //汇率
               public double c;     //手续费               
               Currency( int s1,int s2,double r,double c )
               {
                         this.s1 = s1;
                         this.s2 = s2;
                         this.r = r;
                         this.c = c;                       
               }     
       }
       
       public void Relax( Currency currency )      //主要是参考《算导》里面的松弛技术
       {
              if( this.dis[currency.s2] < (this.dis[currency.s1]-currency.c)*currency.r )
                  this.dis[currency.s2] = (this.dis[currency.s1]-currency.c)*currency.r;
       }

       public boolean isIncrease()        //主要是参考《算导》里面的Bellman-Ford算法
       {
              for( int i=1;i<=n-1;i++ )
              {
                   for( int j=0;j<2*m;j++ )
                   {
                        this.Relax( this.currencies[j] );
                   }
              }
              for( int i=0;i<2*m;i++ )
              {
                   Currency currency = currencies[i];
                   if( this.dis[currency.s2] < (this.dis[currency.s1]-currency.c)*currency.r )
                        return true;
              }

              return false;
       }

       Main( int n,int m,int s,double v )      //初始化
       {
             this.n = n;
             this.m = m;
             this.currencies = new Currency[2*m];
             this.dis = new double[n+1];
             dis[s] = v;
       }
       public void setM( int i,int s1,int s2,double r12,double c12,double r21,double c21 )       //设置初始值
       {
              this.currencies[i] = new Currency( s1,s2,r12,c12 );
              this.currencies[i+1] = new Currency( s2,s1,r21,c21 );
       }
       public static void main(String[] args)
       {
              Scanner s = new Scanner(System.in);
              int n = s.nextInt();
              int m = s.nextInt();
              int S = s.nextInt();
              double v = s.nextDouble();
              int i=0;
              Main main = new Main( n,m,S,v );
              while( i<2*m )
              {
                     int s1 = s.nextInt();
                     int s2 = s.nextInt();
                     double r12 = s.nextDouble();
                     double c12 = s.nextDouble();
                     double r21 = s.nextDouble();
                     double c21 = s.nextDouble();
                     main.setM( i,s1,s2,r12,c12,r21,c21 );    //设置所有的边
                     i+=2;
               }
               if( main.isIncrease() )
                   System.out.println( "YES" );
               else
                   System.out.println( "NO" );
       }
}


这道题目,可以这么理解:一种货币,就是图上的一个点。一种兑换方法,就是这两个点之间的一个环。当货币A的数量为V时,它到货币B的兑换方法为:(A-Cab)*Rab

上式中,Cab为A、B之间的手续费,Rab为兑换率。(A-Cab)*Rab得到的结果为A到B的权值。

题目要我们判断最终的财富是不是可以增加,也就是说,要找到最大的路径。其中,货币的兑换是可以无限次数的,换句话说,只要我们找到一个正的回路,在里面无限循环执行,那么财富肯定可以增加。现在,我们要判断的,就是是不是有这样的回路。这和《算法导论》里面的“负回路”可以说是如出一辙。

所以,我们可以参考Bellman-Ford算法(算法正确性的证明可以参照《算法导论》)

 

好了,下面是废话:

唉,还是不会抽丝剥茧那样进行归纳总结来解决问题。也是参考了《算法导论》和网上的代码http://blog.youkuaiyun.com/lyy289065406/article/details/6645778

在写完之后,还因为没弄好A,B之间的兑换关系,还卡了一会儿,才解决了问题。

看来,分析问题的能力和仔细程度还是有待提高啊。唉!!!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值