Facebook Pixel

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 day i, they earn stayScore[i][curr] points.
  • Move to another city: If the tourist moves from city curr to city dest, they earn travelScore[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.

  1. Dynamic Programming Table: Define a DP table f where f[i][j] represents the maximum score achievable on day i in city j.

  2. Base Case: At day 0, the tourist can start at any city with 0 points, hence f[0][j] = 0 for all j.

  3. Transition: For each day i from 1 to k, and each city j:

    • Stay in city j: Add stayScore[i-1][j] to the score from the previous day in the same city.
    • Move from another city h to city j: Add travelScore[h][j] to the score from the previous day in city h.

    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 ]

  4. Result: After processing all days, the result is the maximum value in f[k], representing the max score obtainable after k 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:

  1. Initialization:

    • We define a 2D list f where f[i][j] will store the maximum points obtainable on day i in city j.
    • Initialize f with -inf values, since we will be looking for the maximum, and set f[0][j] = 0 for all cities j to denote that the journey starts with zero points.
    f = [[-inf] * n for _ in range(k + 1)]
    f[0] = [0] * n
  2. DP Transitions:

    • For each day i from 1 to k and each city j, calculate the maximum points for staying in j or traveling to j from any city h.
    • Use a nested loop: the outer two loops iterate over days i and cities j, and the innermost loop iterates over potential previous cities h.
    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]),
                )
  3. Decision Points:

    • If the tourist decides to stay in city j, they accumulate stayScore[i-1][j] on top of what they had on day i-1.
    • If the tourist travels from city h to city j, they earn travelScore[h][j] in addition to the score from day i-1.
  4. Final Solution:

    • After populating the DP table, the result is the maximum score obtainable on day k across all cities, given by max(f[k]).
    return max(f[k])

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 Evaluator

Example 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 cities j 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
  • 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
  • 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
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
  • 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
  • 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
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.


Discover Your Strengths and Weaknesses: Take Our 2-Minute Quiz to Tailor Your Study Plan:
Question 1 out of 10

Which of the following array represent a max heap?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!


Load More