3332. Maximum Points Tourist Can Earn
Problem Description
You are given two integers, n
(the number of cities) and k
(the number of days), along with two 2D integer arrays, stayScore
and travelScore
.
A tourist is planning a journey across n
cities, where each city is directly connected to every other city. The journey consists of exactly k
days. The tourist can start in any city and has the following choices for each day:
- Stay in the current city: If the tourist stays in city
curr
on dayi
, they earnstayScore[i][curr]
points. - Move to another city: If the tourist moves from city
curr
to citydest
, they earntravelScore[curr][dest]
points.
Your task is to return the maximum possible points the tourist can earn over the k
days.
Intuition
The main objective is to maximize the points gained over the course of k
days. We need to consider both staying in the current city and moving to another city. This suggests a dynamic programming approach where we keep track of the maximum points achievable at each stage for each city.
-
Dynamic Programming Table: Define a DP table
f
wheref[i][j]
represents the maximum score achievable on dayi
in cityj
. -
Base Case: At day 0, the tourist can start at any city with 0 points, hence
f[0][j] = 0
for allj
. -
Transition: For each day
i
from 1 tok
, and each cityj
:- Stay in city
j
: AddstayScore[i-1][j]
to the score from the previous day in the same city. - Move from another city
h
to cityj
: AddtravelScore[h][j]
to the score from the previous day in cityh
.
Formally, update
f[i][j]
as: [ f[i][j] = \max(f[i][j], f[i-1][h] + \text{stayScore}[i-1][j]) \quad \text{if}\ j == h ] [ f[i][j] = \max(f[i][j], f[i-1][h] + \text{travelScore}[h][j]) \quad \text{if}\ j \neq h ] - Stay in city
-
Result: After processing all days, the result is the maximum value in
f[k]
, representing the max score obtainable afterk
days.
This approach efficiently calculates the maximum score by considering both staying and traveling every day, making sure to explore all possibilities and keep the optimal solution.
Learn more about Dynamic Programming patterns.
Solution Approach
The solution employs a dynamic programming (DP) approach to efficiently calculate the maximum points the tourist can earn over the course of k
days. Here is a detailed walk-through of the implementation:
-
Initialization:
- We define a 2D list
f
wheref[i][j]
will store the maximum points obtainable on dayi
in cityj
. - Initialize
f
with-inf
values, since we will be looking for the maximum, and setf[0][j] = 0
for all citiesj
to denote that the journey starts with zero points.
f = [[-inf] * n for _ in range(k + 1)] f[0] = [0] * n
- We define a 2D list
-
DP Transitions:
- For each day
i
from 1 tok
and each cityj
, calculate the maximum points for staying inj
or traveling toj
from any cityh
. - Use a nested loop: the outer two loops iterate over days
i
and citiesj
, and the innermost loop iterates over potential previous citiesh
.
for i in range(1, k + 1): for j in range(n): for h in range(n): f[i][j] = max( f[i][j], f[i - 1][h] + (stayScore[i - 1][j] if j == h else travelScore[h][j]), )
- For each day
-
Decision Points:
- If the tourist decides to stay in city
j
, they accumulatestayScore[i-1][j]
on top of what they had on dayi-1
. - If the tourist travels from city
h
to cityj
, they earntravelScore[h][j]
in addition to the score from dayi-1
.
- If the tourist decides to stay in city
-
Final Solution:
- After populating the DP table, the result is the maximum score obtainable on day
k
across all cities, given bymax(f[k])
.
return max(f[k])
- After populating the DP table, the result is the maximum score obtainable on day
This approach thoroughly evaluates all possibilities of staying or traveling across the cities for each day, thus ensuring the calculated score is indeed the maximum achievable over the specified duration. This use of dynamic programming allows us to handle the complexity efficiently across the various combinations of city itineraries.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's work through a small example to illustrate the solution approach. Suppose we have 3 cities (n = 3
) and the journey lasts 2 days (k = 2
). The stayScore
and travelScore
arrays are given as follows:
stayScore
=[[5, 6, 3], [2, 8, 7]]
travelScore
=[[0, 2, 1], [4, 0, 3], [2, 2, 0]]
Day 0 (Initialization):
- Initialize a DP table
f
with dimensions(k + 1) x n
, filled with-inf
. - Set
f[0][j] = 0
for all citiesj
since the tourist starts with 0 points.
f = [ [0, 0, 0], # Day 0 [-inf, -inf, -inf], # Day 1 [-inf, -inf, -inf] # Day 2 ]
Day 1:
For each city j
, calculate scores considering either staying or coming from another city h
.
-
City 0:
- Stay:
f[1][0] = f[0][0] + stayScore[0][0] = 0 + 5 = 5
- From City 1:
f[1][0] = max(5, f[0][1] + travelScore[1][0] = 0 + 4) = 5
- From City 2:
f[1][0] = max(5, f[0][2] + travelScore[2][0] = 0 + 2) = 5
- Stay:
-
City 1:
- Stay:
f[1][1] = f[0][1] + stayScore[0][1] = 0 + 6 = 6
- From City 0:
f[1][1] = max(6, f[0][0] + travelScore[0][1] = 0 + 2) = 6
- From City 2:
f[1][1] = max(6, f[0][2] + travelScore[2][1] = 0 + 2) = 6
- Stay:
-
City 2:
- Stay:
f[1][2] = f[0][2] + stayScore[0][2] = 0 + 3 = 3
- From City 0:
f[1][2] = max(3, f[0][0] + travelScore[0][2] = 0 + 1) = 3
- From City 1:
f[1][2] = max(3, f[0][1] + travelScore[1][2] = 0 + 3) = 3
- Stay:
f = [ [0, 0, 0], [5, 6, 3], # Calculated scores after day 1 [-inf, -inf, -inf] ]
Day 2:
Similarly, for each city j
, compute potential scores:
-
City 0:
- Stay:
f[2][0] = f[1][0] + stayScore[1][0] = 5 + 2 = 7
- From City 1:
f[2][0] = max(7, f[1][1] + travelScore[1][0] = 6 + 4) = 10
- From City 2:
f[2][0] = max(10, f[1][2] + travelScore[2][0] = 3 + 2) = 10
- Stay:
-
City 1:
- Stay:
f[2][1] = f[1][1] + stayScore[1][1] = 6 + 8 = 14
- From City 0:
f[2][1] = max(14, f[1][0] + travelScore[0][1] = 5 + 2) = 14
- From City 2:
f[2][1] = max(14, f[1][2] + travelScore[2][1] = 3 + 2) = 14
- Stay:
-
City 2:
- Stay:
f[2][2] = f[1][2] + stayScore[1][2] = 3 + 7 = 10
- From City 0:
f[2][2] = max(10, f[1][0] + travelScore[0][2] = 5 + 1) = 10
- From City 1:
f[2][2] = max(10, f[1][1] + travelScore[1][2] = 6 + 3) = 10
- Stay:
f = [ [0, 0, 0], [5, 6, 3], [10, 14, 10] # Calculated scores after day 2 ]
Result:
The maximum score after 2 days is max(f[2]) = 14
, which is achieved by staying in or traveling to city 1 on both days to maximize points.
Solution Implementation
1from typing import List
2from math import inf
3
4class Solution:
5 def maxScore(
6 self, n: int, k: int, stayScore: List[List[int]], travelScore: List[List[int]]
7 ) -> int:
8 # Initialize a 2D list 'f' with size (k+1) x n filled with negative infinity
9 # f[i][j] represents the maximum score reachable on day 'i' at location 'j'.
10 f = [[-inf] * n for _ in range(k + 1)]
11
12 # On day 0, the maximum score for any location is 0
13 f[0] = [0] * n
14
15 # Iterate over each day from 1 to k
16 for day in range(1, k + 1):
17 # Consider each location 'current'
18 for current in range(n):
19 # Explore possible prior locations 'previous'
20 for previous in range(n):
21 # Calculate score for staying or traveling to the location
22 if current == previous:
23 score = stayScore[day - 1][current]
24 else:
25 score = travelScore[previous][current]
26
27 # Update the maximum score at 'current' location on 'day'
28 f[day][current] = max(f[day][current], f[day - 1][previous] + score)
29
30 # Return the maximum score that can be achieved on the last day (day k)
31 return max(f[k])
32
1import java.util.Arrays;
2
3class Solution {
4
5 public int maxScore(int n, int k, int[][] stayScore, int[][] travelScore) {
6 // Initialize the DP table with minimum integer values
7 int[][] dp = new int[k + 1][n];
8 for (int[] row : dp) {
9 Arrays.fill(row, Integer.MIN_VALUE);
10 }
11
12 // At day 0, you can start in any city without any constraint
13 Arrays.fill(dp[0], 0);
14
15 // Iterate through each day
16 for (int day = 1; day <= k; ++day) {
17 // Iterate through each city as the destination
18 for (int destCity = 0; destCity < n; ++destCity) {
19 // Iterate through each city as the starting point
20 for (int startCity = 0; startCity < n; ++startCity) {
21 // Calculate the score for staying or traveling
22 int score;
23 if (destCity == startCity) {
24 // Staying in the same city
25 score = stayScore[day - 1][destCity];
26 } else {
27 // Traveling to another city
28 score = travelScore[startCity][destCity];
29 }
30 // Update DP table with the maximum score
31 dp[day][destCity] = Math.max(dp[day][destCity], dp[day - 1][startCity] + score);
32 }
33 }
34 }
35
36 // Find the maximum score achievable after k days
37 return Arrays.stream(dp[k]).max().getAsInt();
38 }
39}
40
1#include <vector>
2#include <algorithm>
3#include <cstring>
4
5using namespace std;
6
7class Solution {
8public:
9 int maxScore(int n, int k, vector<vector<int>>& stayScore, vector<vector<int>>& travelScore) {
10 int dp[k + 1][n]; // Dynamic programming table to store the scores
11
12 // Initialize the dp array. Set all values to a very negative number to handle min-max correctly
13 memset(dp, 0xc0, sizeof(dp));
14
15 // Base case: On day 0, the score is 0 for starting in any city
16 memset(dp[0], 0, sizeof(dp[0]));
17
18 // Iterate through each day
19 for (int i = 1; i <= k; ++i) {
20 // Iterate through each city as the current city
21 for (int j = 0; j < n; ++j) {
22 // Check all possible previous cities from where we can come to city j
23 for (int h = 0; h < n; ++h) {
24 // If we stay in the same city, use stayScore; otherwise, use travelScore
25 dp[i][j] = max(dp[i][j], dp[i - 1][h] + (j == h ? stayScore[i - 1][j] : travelScore[h][j]));
26 }
27 }
28 }
29
30 // Return the maximum score possible on the last day in any city
31 return *max_element(dp[k], dp[k] + n);
32 }
33};
34
1/**
2 * Computes the maximum score possible by visiting locations over 'k' days.
3 *
4 * @param n - Number of locations.
5 * @param k - Number of days.
6 * @param stayScore - Matrix representing the score for staying in the same location.
7 * @param travelScore - Matrix representing the score for traveling between locations.
8 * @returns Maximum score achievable after 'k' days.
9 */
10function maxScore(n: number, k: number, stayScore: number[][], travelScore: number[][]): number {
11 // Initialize a 2D array 'dp' to store the maximum score at each day and location
12 const dp: number[][] = Array.from({ length: k + 1 }, () => Array(n).fill(-Infinity));
13
14 // Base case: On day 0, the score is 0 no matter the location
15 dp[0].fill(0);
16
17 // Iterate over each day from 1 to k
18 for (let day = 1; day <= k; ++day) {
19 // Iterate over each current location
20 for (let currentLocation = 0; currentLocation < n; ++currentLocation) {
21 // Iterate over each previous location
22 for (let previousLocation = 0; previousLocation < n; ++previousLocation) {
23 // Calculate the score if choosing to stay or travel
24 const currentScore = (currentLocation === previousLocation)
25 ? stayScore[day - 1][currentLocation] // Stay score
26 : travelScore[previousLocation][currentLocation]; // Travel score
27
28 // Update the dp table with the maximum score
29 dp[day][currentLocation] = Math.max(dp[day][currentLocation], dp[day - 1][previousLocation] + currentScore);
30 }
31 }
32 }
33
34 // Find the maximum score after 'k' days across all locations
35 return Math.max(...dp[k]);
36}
37
Time and Space Complexity
The time complexity of the code is O(k * n^2)
. This is because there are three nested loops: the outer loop runs k
times, the middle loop runs n
times for each k
, and the innermost loop also runs n
times for each n
. Therefore, the total number of operations is proportional to k * n * n = k * n^2
.
The space complexity of the code is O(k * n)
because it uses a 2D list f
of size (k + 1) * n
to store intermediate results. This is the dominant space usage in the algorithm.
Learn more about how to find time and space complexity quickly.
Which of the following array represent a max heap?
Recommended Readings
What is Dynamic Programming Prerequisite DFS problems dfs_intro Backtracking problems backtracking Memoization problems memoization_intro Pruning problems backtracking_pruning Dynamic programming is an algorithmic optimization technique that breaks down a complicated problem into smaller overlapping sub problems in a recursive manner and uses solutions to the sub problems to construct a solution
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Want a Structured Path to Master System Design Too? Don’t Miss This!