1. 题目来源
2. 题目解析
我也搞不懂,为什么当时会写一个 dfs 去做这个题目,不如直接 for for for 完事了,思路没有想好,想歪了又很难更正过来啊…
思路:
- 只需要统计一下,每一行最大的三个数分别在哪一列即可。
- 然后暴力枚举第一个车的 行、列。
- 暴力枚举第二个车的 列,此时要求不能与第一个车 同列
- 暴力枚举第三个车的 列,此时要求不能与第一、第二个车 同列。
- 计算答案即可。
坑点:
- 如果开 LL 的话,最大最小值,需要直接设置成 1e18 -1e18。
这一套暴力枚举思想很直接,但实现上比较简洁,代码常数小,所以还是可以通过的。
目前没看到什么好的题解,计算量计算正确的话,直接暴力枚举就行了。
看看 蛙神 的题解和代码实现即可,这里直接 CV 过来吧。
蛙神针对这个题目,做了复杂度分析。还是比较有参考价值的,可以看看。
- 时间复杂度: O ( n m k + ( n k ) 3 ) O(nmk+(nk)^3) O(nmk+(nk)3)
- 空间复杂度: O ( n ) O(n) O(n)
class Solution {
public:
long long maximumValueSum(vector<vector<int>>& board) {
int n = board.size(), m = board[0].size();
typedef pair<int, int> pii;
pii best[n][3];
// 预处理每行最大的三列
for (int i = 0; i < n; i++) {
for (int k = 0; k < 3; k++) best[i][k] = {-1, -2e9};
for (int j = 0; j < m; j++) for (int k = 0; k < 3; k++)
if (board[i][j] > best[i][k].second) {
for (int kk = 2; kk > k; kk--) best[i][kk] = best[i][kk - 1];
best[i][k] = {j, board[i][j]};
break;
}
}
long long ans = -1e18;
// 枚举选哪一行,以及那一行最大的三列里选哪一列
for (int i1 = 0; i1 < n; i1++) for (int k1 = 0; k1 < 3; k1++)
for (int i2 = i1 + 1; i2 < n; i2++) for (int k2 = 0; k2 < 3; k2++) if (best[i2][k2].first != best[i1][k1].first)
for (int i3 = i2 + 1; i3 < n; i3++) for (int k3 = 0; k3 < 3; k3++) if (best[i3][k3].first != best[i1][k1].first && best[i3][k3].first != best[i2][k2].first) {
ans = max(ans, (long long) best[i1][k1].second + best[i2][k2].second + best[i3][k3].second);
break;
}
return ans;
}
};