💥💥 Beats 100% on runtime and memory [EXPLAINED]
IntuitionMaximize the score by selecting grid cells based on certain constraints. We need to consider both the row and column positions to avoid revisiting rows
# Intuition
Maximize the score by selecting grid cells based on certain constraints. We need to consider both the row and column positions to avoid revisiting rows. The solution involves using dynamic programming to efficiently calculate the best score by recursively checking all possibilities, while ensuring no row is selected more than once.

# Approach
Use a DP approach where we recursively explore all cell selections while maintaining a bitmask to track visited rows. At each step, we check whether the current row has already been selected using the bitmask. If not, we attempt to select the cell and move to the next unique value, updating the DP table with the best possible score.

# Complexity
- Time complexity:
O(n * 2^n), where n is the number of rows. This comes from iterating through all subsets of rows (represented by the bitmask) and calculating the best score for each subset.

- Space complexity:
O(n * 2^n), due to the DP table storing results for every possible row subset.

# Code
```kotlin []
class Solution {
    private var visAll: Int = 0
    private lateinit var dp: Array<IntArray>

    private fun solve(idx: Int, mask: Int, valList: List<Pair<Int, Int>>): Int {
        if (idx == valList.size) return 0
        if (mask == visAll) return 0
        if (dp[idx][mask] != -1) return dp[idx][mask]

        val currVal = valList[idx].first
        var nxtUniqueIdx = idx
        while (nxtUniqueIdx < valList.size && valList[nxtUniqueIdx].first == currVal) {
            nxtUniqueIdx++
        }

        var ans = solve(nxtUniqueIdx, mask, valList)

        for (i in idx until nxtUniqueIdx) {
            val curRow = valList[i].second
            if ((mask and (1 shl curRow)) == 0) {  // if row isn't visited
                val tmp = solve(nxtUniqueIdx, mask or (1 shl curRow), valList) + valList[i].first
                ans = maxOf(ans, tmp)
            }
        }

        dp[idx][mask] = ans
        return ans
    }

    fun maxScore(grid: List<List<Int>>): Int {
        val n = grid.size
        val m = grid[0].size

        // Convert List<List<Int>> to Array<IntArray>
        val gridArray = grid.map { it.toIntArray() }.toTypedArray()

        val valList = mutableListOf<Pair<Int, Int>>()
        for (i in 0 until n) {
            for (j in 0 until m) {
                valList.add(Pair(gridArray[i][j], i))
            }
        }

        valList.sortBy { it.first }
        visAll = (1 shl n) - 1
        dp = Array(valList.size) { IntArray(1 shl n) { -1 } }
        return solve(0, 0, valList)
    }
}

```
['Divide and Conquer', 'Dynamic Programming', 'Bit Manipulation', 'Depth-First Search', 'Graph', 'Memoization', 'Heap (Priority Queue)', 'Shortest Path', 'Bitmask', 'Kotlin']