3332. 旅客可以得到的最多点数
给你两个整数 n
和 k
,和两个二维整数数组 stayScore
和 travelScore
。
一位旅客正在一个有 n
座城市的国家旅游,每座城市都 直接 与其他所有城市相连。这位游客会旅游 恰好 k
天(下标从 0 开始),且旅客可以选择 任意 城市作为起点。
每一天,这位旅客都有两个选择:
i
天停留在前一天所在的城市 curr
,旅客会获得 stayScore[i][curr]
点数。curr
前往城市 dest
,旅客会获得 travelScore[curr][dest]
点数。请你返回这位旅客可以获得的 最多 点数。
示例 1:
输入:n = 2, k = 1, stayScore = [[2,3]], travelScore = [[0,2],[1,0]]
输出:3
解释:
旅客从城市 1 出发并停留在城市 1 可以得到最多点数。
示例 2:
输入:n = 3, k = 2, stayScore = [[3,4,2],[2,1,2]], travelScore = [[0,2,1],[2,0,4],[3,2,0]]
输出:8
解释:
旅客从城市 1 出发,第 0 天停留在城市 1 ,第 1 天前往城市 2 ,可以得到最多点数。
提示:
1 <= n <= 200
1 <= k <= 200
n == travelScore.length == travelScore[i].length == stayScore[i].length
k == stayScore.length
1 <= stayScore[i][j] <= 100
0 <= travelScore[i][j] <= 100
travelScore[i][i] == 0
原站题解
python3 解法, 执行用时: 3028 ms, 内存消耗: 19.9 MB, 提交时间: 2024-11-03 22:18:51
class Solution: def maxScore1(self, n: int, k: int, stayScore: List[List[int]], travelScore: List[List[int]]) -> int: @cache # 缓存装饰器,避免重复计算 dfs 的结果(记忆化) def dfs(i: int, j: int) -> int: if i == k: return 0 res1 = dfs(i + 1, j) + stayScore[i][j] # 留在当前城市 j # 注意题目保证 travelScore[j][j]=0,这一定不如留在当前城市优 res2 = max(dfs(i + 1, d) + s for d, s in enumerate(travelScore[j])) # 前往另外一座城市 d return max(res1, res2) return max(dfs(0, j) for j in range(n)) # 枚举城市 j 作为起点 # 递推 def maxScore(self, n: int, k: int, stayScore: List[List[int]], travelScore: List[List[int]]) -> int: f = [[0] * n for _ in range(k + 1)] for i in range(k - 1, -1, -1): for j, ss in enumerate(stayScore[i]): f[i][j] = max(f[i + 1][j] + ss, max(fd + ts for fd, ts in zip(f[i + 1], travelScore[j]))) return max(f[0])
golang 解法, 执行用时: 122 ms, 内存消耗: 8.4 MB, 提交时间: 2024-11-03 22:18:19
func maxScore1(n, k int, stayScore, travelScore [][]int) (ans int) { memo := make([][]int, k) for i := range memo { memo[i] = make([]int, n) } var dfs func(int, int) int dfs = func(i, j int) int { if i == k { return 0 } p := &memo[i][j] if *p > 0 { // 之前计算过 return *p } res := dfs(i+1, j) + stayScore[i][j] // 留在当前城市 j for d, s := range travelScore[j] { // 注意题目保证 travelScore[j][j]=0,这一定不如留在当前城市优 res = max(res, dfs(i+1, d)+s) // 前往另外一座城市 d } *p = res // 记忆化 return res } for j := range n { // 枚举城市 j 作为起点 ans = max(ans, dfs(0, j)) } return } // 递推 func maxScore(n, k int, stayScore, travelScore [][]int) int { f := make([][]int, k+1) f[k] = make([]int, n) for i, row := range slices.Backward(stayScore) { f[i] = make([]int, n) for j, s := range row { f[i][j] = f[i+1][j] + s // s=stayScore[i][j] for d, ts := range travelScore[j] { f[i][j] = max(f[i][j], f[i+1][d]+ts) } } } return slices.Max(f[0]) }
java 解法, 执行用时: 142 ms, 内存消耗: 54.3 MB, 提交时间: 2024-11-03 22:17:30
class Solution { // dfs public int maxScore1(int n, int k, int[][] stayScore, int[][] travelScore) { int[][] memo = new int[k][n]; int ans = 0; // 枚举城市 j 作为起点 for (int j = 0; j < n; j++) { ans = Math.max(ans, dfs(0, j, stayScore, travelScore, k, memo)); } return ans; } private int dfs(int i, int j, int[][] stayScore, int[][] travelScore, int k, int[][] memo) { if (i == k) { return 0; } // 之前计算过 if (memo[i][j] > 0) { return memo[i][j]; } // 留在当前城市 j int res = dfs(i + 1, j, stayScore, travelScore, k, memo) + stayScore[i][j]; // 前往另外一座城市 d for (int d = 0; d < travelScore[j].length; d++) { // 注意题目保证 travelScore[j][j]=0,这一定不如留在当前城市优 res = Math.max(res, dfs(i + 1, d, stayScore, travelScore, k, memo) + travelScore[j][d]); } // 记忆化 return memo[i][j] = res; } // 递推 public int maxScore(int n, int k, int[][] stayScore, int[][] travelScore) { int[][] f = new int[k + 1][n]; for (int i = k - 1; i >= 0; i--) { for (int j = 0; j < n; j++) { f[i][j] = f[i + 1][j] + stayScore[i][j]; for (int d = 0; d < n; d++) { f[i][j] = Math.max(f[i][j], f[i + 1][d] + travelScore[j][d]); } } } int ans = 0; for (int x : f[0]) { ans = Math.max(ans, x); } return ans; } }
cpp 解法, 执行用时: 351 ms, 内存消耗: 57.2 MB, 提交时间: 2024-11-03 22:16:48
class Solution { public: // dp int maxScore1(int n, int k, vector<vector<int>>& stayScore, vector<vector<int>>& travelScore) { vector<vector<int>> memo(k, vector<int>(n)); auto dfs = [&](auto&& dfs, int i, int j) -> int { if (i == k) { return 0; } int& res = memo[i][j]; // 注意这里是引用 if (res) { // 之前计算过 return res; } res = dfs(dfs, i + 1, j) + stayScore[i][j]; // 留在当前城市 j for (int d = 0; d < travelScore[j].size(); d++) { // 注意题目保证 travelScore[j][j]=0,这一定不如留在当前城市优 res = max(res, dfs(dfs, i + 1, d) + travelScore[j][d]); // 前往另外一座城市 d } return res; }; int ans = 0; for (int j = 0; j < n; j++) { // 枚举城市 j 作为起点 ans = max(ans, dfs(dfs, 0, j)); } return ans; } // 递推 int maxScore(int n, int k, vector<vector<int>>& stayScore, vector<vector<int>>& travelScore) { vector<vector<int>> f(k + 1, vector<int>(n)); for (int i = k - 1; i >= 0; i--) { for (int j = 0; j < n; j++) { f[i][j] = f[i + 1][j] + stayScore[i][j]; for (int d = 0; d < n; d++) { f[i][j] = max(f[i][j], f[i + 1][d] + travelScore[j][d]); } } } return ranges::max(f[0]); } };