图算法--套汇问题

套汇问题

       套汇是指利用货币对率的差异,把一个单位的某种货币转换为大于一个单位的同种货币的方法。例如,假定1美元可以买46.4印度卢比,1印度卢比可以买2.5日元,1日元可以买0.0091美元。通过货币兑换,一个商人可以从美元开始买入,得到46.4*2.5*0.0091=1.0556美元,因而获得5.56%的利润。

       假定已知n种货币c1,c2,….,cn和有关兑换率的n*n的表R,1单位货币ci可以买入R[I,j]单位的货币cj.

 

a)       写入一个有效算法,以确定是否存在一个货币序列<ci1,ci2,ci3,ci4,…,cik>满足

R[i1,i2]* R[i2,i3]… R[ik-1,ik] *R[ik,i1] >1

并分析算法的运行时间。

b)      写出一个有效的算法来输出该序列(如果存在这样的序列的话),并分析算法的运行时间。

 

解:

基本解题思想:

通过FLOYD算法求出最大环。判断最大环的权值之积是否大于1,如果大于1说明可以实现套汇,如果不大于1 说明不能实现套汇。在求解最大环的同时记录下兑换过程中的步骤。

 

算法实现的数据结构:

int Path[MAX_VERTECX_NUM][MAX_VERTECX_NUM];//用来记录套汇过程中要经过的路径

float value[MAX_VERTECX_NUM][MAX_VERTECX_NUM];//用来记录经过讨回操作后得到的值

 

//借助图来实现该算法

typedef struct{

        int vexs[MAX_VERTECX_NUM]; //顶点向量 每种货币对应一个顶点

        float arc[MAX_VERTECX_NUM][MAX_VERTECX_NUM];//邻接矩阵 存放兑换率信息

        int vexnum,arcnum;         //图中当前顶点数和弧数

        }MGraph;

 

算法中的关键步骤:

        for(k=1;k<=G->vexnum;k++)

     {

         for(i=1;i<=G->vexnum;i++)

         {

              for(j=1;j<=G->vexnum;j++)

              {            

                  if(value[i][k]*value[k][j]>value[i][j])//对FLOYD算法的修改,这里判断是否使兑换率增大,如果增大则记录下来

                  {

                      value[i][j]=value[i][k]*value[k][j];

                      Path[i][j]=Path[k][j];

                   }                     

               }

          }

  }

 

 

在输出兑换序列时采用了递归算法:这个算法逆序输出了兑换序列。

void Procedure_print(int i,int j)

{

     if(Path[i][j]==i)

     {

            printf("%d",i);       

            return;

     }

     else if(Path[i][j]==0)//输出结点i与结点j之间不存在通路

           printf("NO path");

     else

    {

           printf("%d ",Path[i][j]);   

           Procedure_print(i,Path[i][j]);//{递归,货币I至J中间顶点}

     }

}

 

 

此算法的时间复杂度是:O(v^3)

算法实现代码:

#include<stdio.h>

#define MAX_VERTECX_NUM 20

#define INT_MIN 0

int n;

int Path[MAX_VERTECX_NUM][MAX_VERTECX_NUM];

float value[MAX_VERTECX_NUM][MAX_VERTECX_NUM];

typedef struct{

        int vexs[MAX_VERTECX_NUM]; //顶点向量 可以存储每个顶点的信息

        float arc[MAX_VERTECX_NUM][MAX_VERTECX_NUM];//邻接矩阵 主要存放关于边的信息

        int vexnum,arcnum;         //图中当前顶点数和弧数

  }MGraph;

 

void CreateDG(MGraph *G){

     int i,j,k;

     float w;

     scanf("%d%d",&(G->vexnum),&(G->arcnum));

     printf("G->vexnum=%d,G->arcnum=%d\n",G->vexnum,G->arcnum);

 

     for(i=1;i<=G->vexnum;i++)

     {

          G->vexs[i]=i;

          }

     for(i=1;i<=G->vexnum;i++)

     {

          for(j=1;j<=G->vexnum;j++)

          {

               G->arc[i][j]=INT_MIN;

               }

          }

 

     for(k=1;k<=G->arcnum;k++)

     {

          scanf("%d%d%f",&i,&j,&w);

          G->arc[i][j]=w;

          } 

 

 

 

     }       

 

void ShortestPath_FLOYD(MGraph *G)

{

     int i,j,k;

     for(i=1;i<=G->vexnum;i++)

     {

          for(j=1;j<=G->vexnum;j++)

          {

              if(i==j)

                  value[i][j]=1;

              else

                  value[i][j]=G->arc[i][j];

              if(G->arc[i][j]>INT_MIN)

                  Path[i][j]=i;

              else

                  Path[i][j]=0;                    

              }

          }

 

 

     for(k=1;k<=G->vexnum;k++)

     {

         for(i=1;i<=G->vexnum;i++)

         {

              for(j=1;j<=G->vexnum;j++)

              {            

                  if(value[i][k]*value[k][j]>value[i][j])

                  {

                      value[i][j]=value[i][k]*value[k][j];

                      Path[i][j]=Path[k][j];

                      }                     

                  }

              }

         }

 

     }

 

void Procedure_print(int i,int j)

{

     if(Path[i][j]==i)

     {

            printf("%d",i);       

            return;

     }

     else if(Path[i][j]==0)//输出结点i与结点j之间不存在通路

              printf("NO path");

              else

              {

                  printf("%d ",Path[i][j]);   

                  Procedure_print(i,Path[i][j]);

              }

     }

 

int main()

{

    int i,j;

    MGraph G;

    freopen("data.in","r",stdin);

    freopen("data.out","w",stdout);

 

    CreateDG(&G);

 

 

    ShortestPath_FLOYD(&G);

 

    i=1;                     

    if(value[i][i]>1)

    {

          printf("%f ",value[i][i]);          

          if(Path[i][i]!=0)

              printf("%d%d ",i,i);

          printf("兑换顺序的逆序输出:%d ",i);

          Procedure_print(i,i);  

          printf("\n");          

     }

}

posted @ 2010-06-15 17:37  linux--lgz  阅读(3500)  评论(0编辑  收藏  举报