You are given two matrices: flights
and days
.
flights[i][j] == 1
means there is a direct flight from city i
to city j
. You can always stay in the same city (think of flights[i][i] == 1
for all i
).days[i][w]
represents the maximum vacation days you can spend in city i
during week w
.0
on week 0
. Each week, you can either stay in the same city or fly to another city (if a flight exists). Your goal is to maximize the total number of vacation days over k
weeks (where k
is the number of columns in days
).
flights
and days
are both n x k
matrices, where n
is the number of cities and k
is the number of weeks.Find the maximum total vacation days you can take.
At first glance, this problem looks like a pathfinding or scheduling problem, where each week you can choose to stay or travel, and you want to maximize your reward (vacation days). A brute-force approach would be to try every possible path: for each week, for each city, try all reachable cities and calculate the total days.
However, with up to 100 cities and 100 weeks, the number of possible paths grows exponentially. This makes brute-force infeasible.
We need to optimize by realizing that the state at each week is simply: "Which city am I in, and what week is it?" For each state, we only care about the best possible total vacation days we could have accumulated up to that point. This is a classic setup for Dynamic Programming (DP).
We can use a DP table where dp[week][city]
represents the maximum vacation days we can have if we are in city
at the start of week
. We build up this table week by week, considering all possible transitions (flights or staying put).
Let's break down the solution step by step:
dp[city]
for the current week, and next_dp[city]
for the next week.dp[0] = days[0][0]
; all other cities start as unreachable (e.g., -inf
).i
, if dp[i]
is reachable, consider all cities j
you can fly to (including staying in i
).j
, update next_dp[j]
as the max of its current value and dp[i] + days[j][week]
.dp = next_dp
and continue to the next week.dp
(the best vacation days possible in any city at the end).This approach ensures we only process each state once per week, making the solution efficient.
Let's consider the following example:
Input:
flights = [[0,1,1],[1,0,1],[1,1,0]]
days = [[1,3,1],[6,0,3],[3,3,3]]
Explanation:
dp = [1, -inf, -inf]
(since days[0][0] = 1
).flights[0][1] == 1
and flights[0][2] == 1
), or stay in city 0.1 + days[0][1] = 1 + 3 = 4
1 + days[1][1] = 1 + 0 = 1
1 + days[2][1] = 1 + 3 = 4
dp = [4, 1, 4]
dp = [5, 7, 7]
max([5,7,7]) = 7
Brute-force:
O(n^k)
where n
is the number of cities and k
is the number of weeks.k
), for each city (n
), for each possible previous city (n
), we do a constant amount of work.O(k * n^2)
.O(n)
if we only keep two arrays for current and next week; O(k * n)
if we keep the full DP table.This is efficient enough for the problem constraints.
The Maximum Vacation Days problem is a great example of optimizing a path-finding problem with dynamic programming. By modeling the problem as a series of states (city, week), and only keeping track of the best possible vacation days for each state, we avoid the exponential explosion of brute-force. The DP approach is both efficient and elegant, and can be implemented with a simple nested loop structure.
class Solution:
def maxVacationDays(self, flights, days):
n = len(flights)
k = len(days[0])
dp = [-float('inf')] * n
dp[0] = 0
for week in range(k):
next_dp = [-float('inf')] * n
for i in range(n):
if dp[i] == -float('inf'):
continue
for j in range(n):
if i == j or flights[i][j]:
next_dp[j] = max(next_dp[j], dp[i] + days[j][week])
dp = next_dp
return max(dp)
class Solution {
public:
int maxVacationDays(vector<vector<int>>& flights, vector<vector<int>>& days) {
int n = flights.size(), k = days[0].size();
vector<int> dp(n, INT_MIN);
dp[0] = 0;
for (int week = 0; week < k; ++week) {
vector<int> next_dp(n, INT_MIN);
for (int i = 0; i < n; ++i) {
if (dp[i] == INT_MIN) continue;
for (int j = 0; j < n; ++j) {
if (i == j || flights[i][j]) {
next_dp[j] = max(next_dp[j], dp[i] + days[j][week]);
}
}
}
dp = next_dp;
}
return *max_element(dp.begin(), dp.end());
}
};
class Solution {
public int maxVacationDays(int[][] flights, int[][] days) {
int n = flights.length, k = days[0].length;
int[] dp = new int[n];
Arrays.fill(dp, Integer.MIN_VALUE);
dp[0] = 0;
for (int week = 0; week < k; ++week) {
int[] next_dp = new int[n];
Arrays.fill(next_dp, Integer.MIN_VALUE);
for (int i = 0; i < n; ++i) {
if (dp[i] == Integer.MIN_VALUE) continue;
for (int j = 0; j < n; ++j) {
if (i == j || flights[i][j] == 1) {
next_dp[j] = Math.max(next_dp[j], dp[i] + days[j][week]);
}
}
}
dp = next_dp;
}
int res = 0;
for (int val : dp) res = Math.max(res, val);
return res;
}
}
var maxVacationDays = function(flights, days) {
const n = flights.length, k = days[0].length;
let dp = new Array(n).fill(-Infinity);
dp[0] = 0;
for (let week = 0; week < k; ++week) {
let next_dp = new Array(n).fill(-Infinity);
for (let i = 0; i < n; ++i) {
if (dp[i] === -Infinity) continue;
for (let j = 0; j < n; ++j) {
if (i === j || flights[i][j]) {
next_dp[j] = Math.max(next_dp[j], dp[i] + days[j][week]);
}
}
}
dp = next_dp;
}
return Math.max(...dp);
};