1. The Problem
Given `n` trading posts on a river (1 to `n` downstream) and a cost matrix `R(i, j)` for renting a canoe from post `i` to post `j`, we need to find a sequence of rentals to travel from post 1 to post `n` with the minimum possible total cost.
For example, with 4 posts and a given cost matrix, the cheapest route might be to rent from 1 to 3 (cost 3), then rent from 3 to 4 (cost 2), for a total cost of 5.
2. The Idea: Dynamic Programming
This problem has optimal substructure: the cheapest path to post `i` must contain a cheapest path to some previous post `j`. This allows us to build the solution from the ground up.
Let `MinCost[i]` be the minimum cost to travel from the start (post 1) to post `i`.
- Base Case: The cost to arrive at the starting post is 0. So, `MinCost[1] = 0`.
- Recurrence Relation: To find the minimum cost to reach post `i`, we consider all possible last legs of the journey. We could have arrived from any upstream post `j` (where `1 <= j < i`). The cost of such a path would be the minimum cost to get to that post `j` (`MinCost[j]`) plus the direct rental cost from `j` to `i` (`R(j, i)`). We take the minimum over all possible previous posts `j`.
We compute `MinCost[i]` for `i = 2, 3, ..., n`. The final answer is the value stored in `MinCost[n]`.
3. The Algorithm
- Create a 1D array, `MinCost`, of size `n+1`. Initialize `MinCost[1] = 0` and `MinCost[i] = infinity` for `i > 1`.
- Create a 1D array, `Path`, of size `n+1` to store the predecessor post for the optimal path. This will help reconstruct the sequence of rentals.
- Iterate with `i` from 2 to `n` (our destination post).
- Iterate with `j` from 1 to `i-1` (the potential starting post for the last leg).
- If `MinCost[j] + R(j, i) < MinCost[i]`, then we have found a cheaper path to `i`.
Update `MinCost[i] = MinCost[j] + R(j, i)`.
Record the path: `Path[i] = j`.
- If `MinCost[j] + R(j, i) < MinCost[i]`, then we have found a cheaper path to `i`.
- Iterate with `j` from 1 to `i-1` (the potential starting post for the last leg).
- The minimum cost is `MinCost[n]`. The path can be found by backtracking from `n` using the `Path` array.
4. Complexity Analysis
- Time Complexity: O(n²)
- The algorithm consists of two nested loops. The outer loop (`i`) runs `n-1` times, and the inner loop (`j`) runs up to `n-1` times. This gives a total number of operations proportional to `(n-1)(n-2)/2`, which is O(n²). This is a polynomial time complexity.
- Space Complexity: O(n)
- We use two 1D arrays, `MinCost` and `Path`, both of size `n+1`. This requires O(n) additional space.