這一題我原先使用了brute force找出所有的換匯途徑,再檢查是否獲利,但這樣會超過time limit,有效率的解法必須使用Floyd-Warshall演算法。參考了Mat所轉錄的文章,研究了一陣,才了解Floyd-Warshall演算法一層層找最佳中繼點,最後再重建路徑回去的方法!但想通了真覺得Floyd-Warshall很美妙呢!
這題可說是找一個weighted graph從一點開始再回到一點的最短路徑,例如(0,.., 0),先找第一個最佳中繼點(0, k1, 0),紀錄下這個k1後,再找第二層中繼點(k1, k2, 0),再紀錄下k2然後繼續…。最後,再從最後kn中繼點,重建回k1,便可以重建(0, k1, k2, .., kn, 0)的完整路徑了。
在我的code裡面,我一找到獲利的路徑後就跳出floyd-warshall。跟這題奮鬥多天的結果是Runtime 0.044,Rank 88!開心!
CODE
#include <stdio.h> #define MAX 20 double profit[MAX][MAX][MAX]; int n, st, path[MAX][MAX][MAX]; int fw(void); int main(){ int i, j, s; int final[MAX]; while( scanf("%d", &n) != EOF ){ /*initialize profit array*/ for(s=0; s<n; s++){ for(i=0; i<n; i++){ for(j=0; j<n; j++){ profit[s][i][j] = 0.0; }/*j*/ }/*i*/ }/*s*/ /*read rates table*/ for(i=0; i<n; i++){ for(j=0; j<n; j++){ if( i==j ) profit[0][i][j] = 1.0; else scanf("%lf", &profit[0][i][j]); path[0][i][j] = i; } } /*Floyd-Warshall*/ if( (s = fw()) > 0 ){ /*Re-construct path*/ final[0] = j = st; i = s; for(i; i>0; i--){ final[i] = path[i][st][j]; j = final[i]; } for(i=0; i<=s; i++){ printf("%d ", final[i]+1); } printf("%d\n", st+1); } else{ printf("no arbitrage sequence exists\n"); } }/*while input data*/ exit(0); } /*Return step when arbitrage exists; Return 0 when no arbitrage exists*/ int fw(void){ int i, j, k, p; int s; double tmp; for(s=1; s<n; s++){ for(k=0; k<n; k++){ for(i=0; i<n; i++){ for(j=0; j<n; j++){ tmp = profit[s-1][i][k] * profit[0][k][j]; if( tmp > profit[s][i][j] ){ profit[s][i][j] = tmp; path[s][i][j] = k; } }/*j*/ }/*i*/ }/*k: intermediate node*/ /*check if arbitrage exists*/ for(p=0; p<n; p++){ if( profit[s][p][p] > 1.01 ){ st = p; return s; } } }/*s: step*/ return 0; }
No comments:
Post a Comment