POJ2240 Arbitrage

http://poj.org/problem?id=2240

題目大意:輸入一些幣種,輸入這些幣種的匯率,求是否存在套匯(套匯及利用匯率之間的差異,從而將某一單位的幣種,兌換回多於一單位的同種貨幣)。

思路:建立圖論模型,每種幣種爲頂點,兩種幣種間的匯率爲一條有向邊,構造好有向網後,問題轉化爲判斷圖中是否存在某個頂點,從它出發的某條迴路權值乘積大於1,大於1則存在套匯。具體求解時,可用Bellman-ford算法求從源點出發到各個頂點v(包括源點自己)。

Bellman-ford算法實現原理爲:用一個dist數組記錄最短路徑,共更新k次(1<k<n),共n-1次,代表當前點到源點經過k條邊,求最短路徑時取最小值,依次更新。用鄰接矩正實現時時間複雜度爲n^3.

//以求最短路徑爲例,允許存在負權值邊,但不允許負權值迴路
//初始化
for  (i=0;i<n;i++)   //n代表頂點個數
      dist[i]=edge[v0][i];  //v0代表源點,此時表示源點經過一條邊到達各個頂點V的距離長度
//一下共循環n-2更新最短路徑
for (k=2;k<n;k++)
{
    for (i=0;i<n;i++)
   {
       for (j=0;j<n;j++)
      {
            if (edge[i][j]!=INF&&edge[i][j]+dist[i]<dist[j])  //如i到j有邊相連,並且此路勁更短,則更新。
            {
                dist[j]=dist[j]+edge[i][j];
            }
      }
   }
}

此題只需將bellman-ford稍加變形便可實現,因套匯必形成迴路,形成迴路最多有n條邊,及只需要將最長路徑更新n次即可判斷是否存在套匯。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 900
#define INF 0xfffffff
char s[MAX][MAX];
typedef struct node
{       
        int u,v;
        float w;
}node;
node map[MAX];
float dist[MAX];
int n,m;
int Max(int x,int y)
{
    return x>y?x:y;
}
int bellman_ford(int v0)   
{
    int i,j,k;
    memset(dist,0,sizeof(dist));
    dist[v0]=1;
    for (k=0;k<n;k++)     //形成迴路,最多有n條邊,循環n次。
    {
        for (i=0;i<m;i++)
        {
            if (dist[map[i].v]<dist[map[i].u]*map[i].w)    
            {
                dist[map[i].v]=dist[map[i].u]*map[i].w; 
            }           
        }                          
    }
    if (dist[v0]>1)   //若源點幣種大於1,則使用該幣種兌換可以實現套匯。
       return 1;
    return 0;     
}
int main()
{
    int tot=0;
    while (~scanf("%d",&n))
    {
          if (n==0)
             break;
          int i,j,u,v,flag=0;
          char sa[MAX],sb[MAX];
          float ans;
          for (i=0;i<n;i++)
          {
              scanf("%s",s[i]);   
          }      
          scanf("%d",&m);
          for (i=0;i<m;i++)
          {
              getchar();
              scanf("%s %f %s",sa,&ans,sb);    
              for (j=0;j<n;j++)
              {
                  if (strcmp(sa,s[j])==0)
                     u=j;
                  if (strcmp(sb,s[j])==0)
                     v=j;    
              }
              map[i].u=u;
              map[i].v=v;
              map[i].w=ans;
          }
          for (i=0;i<n;i++)
          {
              if (bellman_ford(i))   //存在套匯則不需要繼續往下判斷。
              {
                 flag=1;
                 break;                    
              }    
          }
          printf("Case %d: ",++tot);
          if (flag)
          {
             printf("Yes\n");             
          }
          else
          {
             printf("No\n");        
          }
    }
    return 0;    
} 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章