classSolution { public: // the meaning of dp[i][j]: // with maxVal of i, and we can choose from the rows // not marked by j, what's the maximum value we can get vector<vector<int>> dp; vector<int> nums; map<int, int> valToRow;
intmaxScore(vector<vector<int>>& grid){ int m = grid.size(), n = grid[0].size(); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { int x = grid[i][j]; valToRow[x] |= 1 << i; } } for (auto&[num, _] : valToRow) { nums.push_back(num); } ranges::sort(nums); int size = nums.size(); dp.resize(size, vector<int>(2 << m, -1)); int res = dfs(size - 1, 0); return res; }
intdfs(int idx, int k){ if (idx < 0) { return0; } if (dp[idx][k] != -1) { return dp[idx][k]; } int res = 0, x = nums[idx]; for (int i = valToRow[x], bit; i; i ^= bit) { bit = i & -i; if (!(k & bit)) { res = max(res, dfs(idx - 1, k | bit) + x); } } if (!res) { res = dfs(idx - 1, k); } dp[idx][k] = res; return res; } };
classSolution { public: // the meaning of dp[i][j]: // with maxVal of i, and we can choose from the rows // not marked by j, what's the maximum value we can get vector<vector<int>> dp; vector<unordered_set<int>> valToRow;
intmaxScore(vector<vector<int>>& grid){ int maxVal = 0, m = grid.size(), n = grid[0].size(); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { maxVal = max(maxVal, grid[i][j]); } } dp.resize(maxVal + 1, vector<int>(2 << m, -1)); // valToRow is to avoid duplication and simplify the iteration valToRow.resize(maxVal + 1); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { valToRow[grid[i][j]].insert(i); } } int res = dfs(maxVal, 0); return res; }
intdfs(int maxVal, int k){ if (maxVal <= 0) { return0; } if (dp[maxVal][k] != -1) { return dp[maxVal][k]; } int res = dfs(maxVal - 1, k); for (int row : valToRow[maxVal]) { if (!(k >> row & 1)) { res = max(res, dfs(maxVal - 1, k | 1 << row) + maxVal); } } dp[maxVal][k] = res; return res; } };