# VNOI - Coding Challenge #3 - Đổ Xăng
## Đề bài
Cho một đồ thị vô hướng liên thông gồm $n$ đỉnh và $m$ cạnh có dạng $(x, y, w)$ nối đỉnh $x$ và đỉnh $y$ và có trọng số $w$, muốn đi qua cạnh này ta cần tiêu thụ $w$ lít xăng.
Cho trước hai đỉnh $st$ và $en$, ta cần tìm cách di chuyển từ đỉnh $st$ đến đỉnh $en$ thông qua $m$ cạnh trên đồ thị, lít xăng tối đa ta có thể có ở một thời điểm là $t$, ban đầu ở đỉnh $st$ ta không có lít xăng nào.
Có $s$ đỉnh có trạm xăng, trạm xăng thứ $i$ được phân bố ở đỉnh $p_i$ và có chi phí cho một lít xăng là $c_i$. Ở mỗi trạm xăng có thể mua tùy ý lượng xăng miễn sao lượng xăng hiện có không vượt qua sức chứa $t$.
Yêu cầu: Tìm số tiền ít nhất cần bỏ ra để đi từ đỉnh $st$ đến đỉnh $en$.
## Subtask 1, 2: $t \leq 500$
Gọi $d(u, t)$ là số tiền nhỏ nhất để đi từ đỉnh $st$ đến đỉnh $u$ và còn lại $t$ lít xăng khi đến đỉnh $u$.
Xét một trạng thái $d(u, t)$ và một cạnh $(u, v, w)$, ta chuyển trạng thái như sau:
- Khi có trạm xăng tại $u$: $d(u, t + 1) \leftarrow d(u, t) + c_u$
- Khi $t \geq w$: $d(v, t - w) \leftarrow d(u, t)$
Để tính $d$, ta sử dụng thuật toán **Dijkstra**.
Độ phức tạp: $O(n \times t \times \log_{2}(n))$
## Subtask 3:
Giả sử các trạm xăng mà ta lần lượt đi qua và có mua ít nhất một lít xăng trên một đường đi tối ưu là $k_1, k_2, \ldots k_l$. Ta nhận thấy chi phí của trạm tiếp theo luôn nhỏ hơn hoặc bằng chi phí của trạm trước, tức $c_{k_i} \geq c_{k_{i + 1}}$ với mọi $i \in [1, l - 1]$.
Từ đây ta sẽ sắp xếp thứ tự các trạm theo chi phí mua giảm dần, gọi $cost_i$ là chi phí mua một lít xăng ở trạm thứ $i$ trong tổng cộng $s$ trạm. Ta gọi $d(i, j)$ là số lít xăng ít nhất cần sử dụng để đi từ trạm thứ $i$ đến trạm thứ $j$ theo thứ tự sắp xếp, ta tính $d$ bằng cách sử dụng thuật toán **Dijkstra**.
Sau đó sử dụng thuật toán quy hoạch động để tính chi phí nhỏ nhất. Xét thứ tự các trạm đã được sắp xếp, ta gọi $dp(i, j)$ là số tiền nhỏ nhất để đi từ đỉnh $st$ đến trạm thứ $i$ theo thứ tự các trạm và còn lại $j$ lít xăng, ta chuyển trạng thái như sau:
- Mua xăng tại trạm thứ $i$: $dp(i, j) \leftarrow dp(i, j - 1) + cost_i$
- Di chuyển giữa các trạm: $dp(i, j) \leftarrow dp(l, j + d(l, i))$ với $l < i; j + d(l, i) \leq t$
Sau khi tính $dp$, ta xét các trạng thái $dp(i, j)$, nếu lượng xăng ít nhất cần dùng để đi từ trạm thứ $i$ đến đỉnh $en$ không vượt quá $j$, ta sẽ xét chúng làm số tiền nhỏ nhất cần bỏ ra.
Độ phức tạp: $O(s \times n + s^2 \times t)$