(a) 建立一个有向图G(V,E),每个顶点表示一种货币,两个顶点之间的边权的大小ex[u][v]表示两种货币之间的汇率,若要找一个最有利的兑换序列,把货币s兑换成货币t,即在若干种兑换序列中选择一条合适的兑换序列,将等量货币s尽可能多的兑换货币t,令money[x]表示一个s币可以兑换多少个x币。初始时令money[s]=1,money[x]=0.利用bellman-ford算法,修改算法中的update过程如下
do for each edge (u, v) ∈ E[G]
if(money[v]<money[u]*ex[u][v])
money[v]=money[u]*ex[u][v]
如果不存在异常情形,则兑换的最长路径最多有n-1条边(n为货币的种数).
(b) 若存在异常情形,则在求得最多n-1条边的基础上再进行依次update操作,某个顶点的money一定增加。

1 package org.xiu68.ch04.ex12; 2 3 public class Ex4_21 { 4 5 public static void main(String[] args) { 6 // TODO Auto-generated method stub 7 8 double max=10000000; 9 10 double[][] edges=new double[][]{ 11 {1,10,5,3}, 12 {0.05,1,0,5}, 13 {0.1,0,1,2}, 14 {0.01,0.15,0.1,1} 15 }; 16 MGraph1 m1=new MGraph1(edges); 17 m1.bellmanFord(0, 3); 18 //输出 19 /* 20 1个第0种货币最多可以兑换50.0个第3种货币 21 不存在异常情况 22 */ 23 24 double[][] edges1=new double[][]{ 25 {1,10,5,3}, 26 {0.05,1,0,5}, 27 {0.1,0,1,2}, 28 {0.2,0.15,0.1,1} 29 }; 30 MGraph1 m2=new MGraph1(edges1); 31 m2.bellmanFord(0, 3); 32 //输出 33 /* 34 1个第0种货币最多可以兑换5000.0个第3种货币 35 存在异常情况 36 */ 37 } 38 39 } 40 41 class MGraph1{ 42 private double[][] edges; //有向图边集 43 private int vexNum; //顶点数目 44 private double[] money; //money[i]表示用一个s币可以兑换多少i币 45 46 public MGraph1(double[][] edges){ 47 this.edges=edges; 48 this.vexNum=edges.length; 49 this.money=new double[vexNum]; 50 } 51 52 public void bellmanFord(int s,int t){ 53 //初始化money数组 54 for(int i=0;i<vexNum;i++){ 55 money[i]=0; 56 } 57 money[s]=1; 58 59 for(int i=1;i<vexNum;i++){ //从源点到任何一个顶点最多有vexNum条边的最短路径 60 boolean flag=false; //记录在本次循环中从源点到某个顶点是否有更短的路径 61 //遍历所有的边 62 for(int j=0;j<vexNum;j++){ 63 for(int k=0;k<vexNum;k++){ 64 if(edges[j][k]!=0 && money[k]<money[j]*edges[j][k]){ 65 money[k]=money[j]*edges[j][k]; 66 flag=true; 67 } 68 } 69 } 70 if(flag==false) //已经求得所有顶点最多edgeNum条边的最短路径 71 break; 72 } 73 74 System.out.println("1个第"+s+"种货币最多可以兑换"+money[t]+"个第"+t+"种货币"); 75 76 boolean flag=false; 77 for(int i=0;i<vexNum;i++){ 78 for(int j=0;j<vexNum;j++){ 79 if(Math.abs(edges[i][j])!=0 && money[j]<money[i]*edges[i][j]){ 80 flag=true; 81 } 82 } 83 } 84 if(flag==false) 85 System.out.println("不存在异常情况"); 86 else 87 System.out.println("存在异常情况"); 88 System.out.println(); 89 } 90 }