Maximum Points Tourist Can Earn
MediumUpdated: Aug 2, 2025
Practice on:
Problem
You are given two integers, n and k, along with two 2D integer arrays,
stayScore and travelScore.
A tourist is visiting a country with n cities, where each city is
directly connected to every other city. The tourist's journey consists of
exactly k 0-indexed days, and they can choose any city as their starting point.
Each day, the tourist has two choices:
- Stay in the current city : If the tourist stays in their current city
currduring dayi, they will earnstayScore[i][curr]points. - Move to another city : If the tourist moves from their current city
currto citydest, they will earntravelScore[curr][dest]points.
Return the maximum possible points the tourist can earn.
Examples
Example 1
Input: n = 2, k = 1, stayScore = [[2,3]], travelScore = [[0,2],[1,0]]
Output: 3
Explanation:
The tourist earns the maximum number of points by starting in city 1 and
staying in that city.
Example 2
Input: n = 3, k = 2, stayScore = [[3,4,2],[2,1,2]], travelScore =
[[0,2,1],[2,0,4],[3,2,0]]
Output: 8
Explanation:
The tourist earns the maximum number of points by starting in city 1, staying
in that city on day 0, and traveling to city 2 on day 1.
Constraints
1 <= n <= 2001 <= k <= 200n == travelScore.length == travelScore[i].length == stayScore[i].lengthk == stayScore.length1 <= stayScore[i][j] <= 1000 <= travelScore[i][j] <= 100travelScore[i][i] == 0
Solution
Method 1 – Dynamic Programming (Bottom-Up)
Intuition
At each day and city, the tourist can either stay or move. We want to maximize the total points by making optimal choices at each step. Since the tourist can start at any city, we try all possible starting cities and use dynamic programming to avoid recomputation.
Approach
- Let
dp[i][j]be the maximum points the tourist can earn starting from dayiat cityj. - For the last day, the only option is to stay:
dp[k-1][j] = stayScore[k-1][j]for allj. - For previous days, for each city
j:- Option 1: Stay in city
jand addstayScore[i][j]todp[i+1][j]. - Option 2: Move to any other city
m(m ≠ j), addtravelScore[j][m]todp[i+1][m]. - Take the maximum of all options.
- Option 1: Stay in city
- The answer is the maximum value among all
dp[0][j](for all starting citiesj).
Code
C++
class Solution {
public:
int maximumPoints(vector<vector<int>>& stayScore, vector<vector<int>>& travelScore) {
int k = stayScore.size(), n = stayScore[0].size();
vector<vector<int>> dp(k, vector<int>(n, 0));
for (int j = 0; j < n; ++j) dp[k-1][j] = stayScore[k-1][j];
for (int i = k-2; i >= 0; --i) {
for (int j = 0; j < n; ++j) {
int ans = stayScore[i][j] + dp[i+1][j];
for (int m = 0; m < n; ++m) {
if (m != j) ans = max(ans, travelScore[j][m] + dp[i+1][m]);
}
dp[i][j] = ans;
}
}
return *max_element(dp[0].begin(), dp[0].end());
}
};
Go
func maximumPoints(stayScore [][]int, travelScore [][]int) int {
k, n := len(stayScore), len(stayScore[0])
dp := make([][]int, k)
for i := range dp {
dp[i] = make([]int, n)
}
for j := 0; j < n; j++ {
dp[k-1][j] = stayScore[k-1][j]
}
for i := k-2; i >= 0; i-- {
for j := 0; j < n; j++ {
ans := stayScore[i][j] + dp[i+1][j]
for m := 0; m < n; m++ {
if m != j && travelScore[j][m]+dp[i+1][m] > ans {
ans = travelScore[j][m] + dp[i+1][m]
}
}
dp[i][j] = ans
}
}
res := dp[0][0]
for j := 1; j < n; j++ {
if dp[0][j] > res {
res = dp[0][j]
}
}
return res
}
Java
class Solution {
public int maximumPoints(int[][] stayScore, int[][] travelScore) {
int k = stayScore.length, n = stayScore[0].length;
int[][] dp = new int[k][n];
for (int j = 0; j < n; ++j) dp[k-1][j] = stayScore[k-1][j];
for (int i = k-2; i >= 0; --i) {
for (int j = 0; j < n; ++j) {
int ans = stayScore[i][j] + dp[i+1][j];
for (int m = 0; m < n; ++m) {
if (m != j) ans = Math.max(ans, travelScore[j][m] + dp[i+1][m]);
}
dp[i][j] = ans;
}
}
int res = dp[0][0];
for (int j = 1; j < n; ++j) res = Math.max(res, dp[0][j]);
return res;
}
}
Kotlin
class Solution {
fun maximumPoints(stayScore: Array<IntArray>, travelScore: Array<IntArray>): Int {
val k = stayScore.size
val n = stayScore[0].size
val dp = Array(k) { IntArray(n) }
for (j in 0 until n) dp[k-1][j] = stayScore[k-1][j]
for (i in k-2 downTo 0) {
for (j in 0 until n) {
var ans = stayScore[i][j] + dp[i+1][j]
for (m in 0 until n) {
if (m != j) ans = maxOf(ans, travelScore[j][m] + dp[i+1][m])
}
dp[i][j] = ans
}
}
return dp[0].maxOrNull() ?: 0
}
}
Python
class Solution:
def maximumPoints(self, stayScore: list[list[int]], travelScore: list[list[int]]) -> int:
k, n = len(stayScore), len(stayScore[0])
dp: list[list[int]] = [[0]*n for _ in range(k)]
for j in range(n):
dp[k-1][j] = stayScore[k-1][j]
for i in range(k-2, -1, -1):
for j in range(n):
ans = stayScore[i][j] + dp[i+1][j]
for m in range(n):
if m != j:
ans = max(ans, travelScore[j][m] + dp[i+1][m])
dp[i][j] = ans
return max(dp[0])
Rust
impl Solution {
pub fn maximum_points(stay_score: Vec<Vec<i32>>, travel_score: Vec<Vec<i32>>) -> i32 {
let k = stay_score.len();
let n = stay_score[0].len();
let mut dp = vec![vec![0; n]; k];
for j in 0..n {
dp[k-1][j] = stay_score[k-1][j];
}
for i in (0..k-1).rev() {
for j in 0..n {
let mut ans = stay_score[i][j] + dp[i+1][j];
for m in 0..n {
if m != j {
ans = ans.max(travel_score[j][m] + dp[i+1][m]);
}
}
dp[i][j] = ans;
}
}
*dp[0].iter().max().unwrap()
}
}
TypeScript
class Solution {
maximumPoints(stayScore: number[][], travelScore: number[][]): number {
const k = stayScore.length, n = stayScore[0].length;
const dp: number[][] = Array.from({length: k}, () => Array(n).fill(0));
for (let j = 0; j < n; ++j) dp[k-1][j] = stayScore[k-1][j];
for (let i = k-2; i >= 0; --i) {
for (let j = 0; j < n; ++j) {
let ans = stayScore[i][j] + dp[i+1][j];
for (let m = 0; m < n; ++m) {
if (m !== j) ans = Math.max(ans, travelScore[j][m] + dp[i+1][m]);
}
dp[i][j] = ans;
}
}
return Math.max(...dp[0]);
}
}
Complexity
- ⏰ Time complexity:
O(k * n^2), wherekis the number of days andnis the number of cities. For each day and city, we check all possible moves. - 🧺 Space complexity:
O(k * n), for the DP table.