### [ACM] Some hints about uva 104 (Modified Floyd-Warshall)

by gits
Original Thread http://online-judge.uva.es/board/viewtopic.php?t=7292

Well, I'll assume you understand what the problem asks. You have to find the shortest sequence that yelds a profit (not the one with the greatest profit!). If there is more then one sequence with the same length, any of those is valid.

Now, you can't just try with brute force (trying all combinations) because it'll be too slow and you'll get Time Limit Exceeded. However, there's a well known algorithm, Floyd-Warshall, which will find all the shortest paths between every node to the others in just O(n^3) time. You can find more info about F-W in the net. In my previous post I said how you have to change the general F-W algorithm to work for this particular problem...

As for floating point errors, most numbers representation isn't totally acurate; for instance, 0.1 is usually stored as 0.10000000000000001. After some operations, the error may influence the final result. Again, search the net for floating point errors. However, you won't have to deal with these errors to solve this problems (at least I didn't).

Hope this helps

=================================
Floyd-Warshall finds all the mininum paths between every vertex and all the other vertexes. However, in this problem you not only have to find the shortest path, it also has to make a profit of more than 1%.

Simple F-W goes like this:
```// initialization
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
best[i][j] = path[i][j];
path[i][j] = i;
}
}

for (k = 0; k < n; k++) {
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
if (best[i][k] + best[k][j] < best[i][j]) {
best[i][j] = best[i][k] + best[k][j];
path[i][j] = k;
}
}
}
}
```

For this problem, instead of having best[i][j] and path[i][j] I have best[i][j][s] and path[i][j][s], which means "best path from i to j in s steps". I also have an outer loop, representing the number of steps.
```// initialization
best[i][j][s] = 0, for all i,j,s
best[i][j] = input for the program
best[i][i] = 1, for all i
path[i][j] = i, for all i, j

for (steps = 2; steps <= n; steps++)
for k...
for i..
for j..
tmp = best[i][k][steps-1] * best[k][j]
if (tmp > best[i][j][steps]) {
best[i][j][steps] = tmp;
path[i][j][steps] = k;
}
```
What we are doing is to find the most profitable way to go from i to j in "steps" steps, trying for each to use k as the point just before j. As you can see, this is O(n^4) but since max n is 20 it's ok.

After this, you scan though best[i][i][s] (best way to go from i to i again, in s steps). Remember that you want the minimum number of steps that yields a profit; so it's this:
```for (steps = 2; steps <= n; steps++)
for (i = 0; i < n; i++)
if (best[i][i][steps] > 1.01) {
// score!
}
```
If the "if" never matches, then there is no arbitrage sequence. If it matches, you have to print the path. To print the path, use path[i][i][steps], which is the vertex just before the last (i).

For instance, if i is 1 and steps is 4. Check path. Suppose it is 2. So the path ends with "... 2 1". Now check path. Supposing it's 4, the path ends with "... 4 2 1". Now check path. If it's 5, the path is "... 5 4 2 1". Finally check path, which will be obviously 1. So the complete path is "1 5 4 2 1" (exactly 4 steps).

Just remember that path[i][j][s] is the vertex which is before the last one in a path from i to j in s steps. If s is 1, the path is simply "i j". In this problem you have to start and finish in the same currency; that's why we only search in best[i][i][steps].

Hope this helps, I almost wrote the complete program!

You could also stop the algorithm as soon as you found a solution. In other posts, some people talked about a O(n^3) solution but I can't figure it out... if someone has such a solution please mail it to me, I would love to learn how to do this in a better way.

Good luck and happy coding!

### 讀書心得: 撒哈拉的故事

「撒哈拉的故事」是三毛與她的丈夫荷西在撒哈拉沙漠旅遊生活的紀實，生活在沙漠很糟糕，至少我看完最後一篇『白手成家』後認為實在很糟，不過在樂觀又開朗的三毛的筆下，撒哈拉沙漠化為一個有趣又不可思議的國度，說著一個又一個異國的故事。

### 8. 使用視圖與相機鏡頭轉換，及 gluLookAt() - OpenGL FAQ

8.010 OpenGL裡的相機鏡頭到底是怎麼運作的呢?  就目前的OpenGL來說，沒有相機鏡頭這種東西。更精確地講，相機永遠都位處於眼空間座標的原點 (0,0,0)。你的OpenGL應用程式為了假裝出移動相機的樣子，必須移動場景，對整個世界場景做相機鏡頭的逆空間轉換。

8.020 我要如何移動場景裡的眼睛或者相機鏡頭? 以相機鏡頭模型來說，OpenGL 並沒有提供介面去做這件事情。然而，GLU庫提供了gluLookAt()函數，傳入眼睛本身位置，眼睛瞄準點位置，以及朝上向量，都是世界空間坐標。這個函數依據參數計算出正確的相機逆空間轉換矩陣，並且乘上目前的矩陣。

8.030 我的相機鏡頭應該放在 ModelView 矩陣還是 Projection矩陣? GL_PROJECTION 矩陣只應該包含投影變換，它必須將眼空間坐標(eye space coordinates)轉換到裁切坐標(clip coordinates)。

GL_MODELVIEW矩陣呢，如其名，應該包含模型(modeling)與視圖(viewing)轉換，將物體空間坐標轉換成眼空間座標。所以請記住，永遠把相機鏡頭轉換放在GL_MODELVIEW矩陣，而不是GL_PROJECTION矩陣。

8.040 我該如何實現鏡頭變焦 (Zoom) 的操作? 簡單的做法是對 ModelView矩陣做等比縮放(uniform scale)。但是當模型放得太大時，通常會導致模型被近平面及遠平面裁切掉。一個比較好的做法是限縮投影矩陣裡view volume的寬與高。舉例來說，你的程式對應使用者的輸入，儲存了一個縮放參數值。當縮放值是1.0 時不變焦。縮放值變大就縮小視角，結果模型看起來就放大了。縮放值變小時就反過來做。程式碼範例看起來可能像這樣子:
/* 如果…

### UVa 10018 Reverse and Add

PS.這題我不小心把某個unsigned long打成int，抓了好久的bug。