<p>You are given a 2D matrix <code>grid</code> consisting of positive integers.</p>

<p>You have to select <em>one or more</em> cells from the matrix such that the following conditions are satisfied:</p>

<ul>
	<li>No two selected cells are in the <strong>same</strong> row of the matrix.</li>
	<li>The values in the set of selected cells are <strong>unique</strong>.</li>
</ul>

<p>Your score will be the <strong>sum</strong> of the values of the selected cells.</p>

<p>Return the <strong>maximum</strong> score you can achieve.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">grid = [[1,2,3],[4,3,2],[1,1,1]]</span></p>

<p><strong>Output:</strong> <span class="example-io">8</span></p>

<p><strong>Explanation:</strong></p>

<p><img alt="" src="https://assets.leetcode.com/uploads/2024/07/29/grid1drawio.png" /></p>

<p>We can select the cells with values 1, 3, and 4 that are colored above.</p>
</div>

<p><strong class="example">Example 2:</strong></p>

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">grid = [[8,7,6],[8,3,2]]</span></p>

<p><strong>Output:</strong> <span class="example-io">15</span></p>

<p><strong>Explanation:</strong></p>

<p><img alt="" src="https://assets.leetcode.com/uploads/2024/07/29/grid8_8drawio.png" style="width: 170px; height: 114px;" /></p>

<p>We can select the cells with values 7 and 8 that are colored above.</p>
</div>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= grid.length, grid[i].length &lt;= 10</code></li>
	<li><code>1 &lt;= grid[i][j] &lt;= 100</code></li>
</ul>

from typing import List, Generator

class Solution:
    def maxScore(self, grid: List[List[int]]) -> int:
        n = len(grid)
        m = len(grid[0])

        def generate_value_to_rows() -> Generator[List[int], None, None]:
            for _ in range(101):
                yield []

        value_to_rows = list(generate_value_to_rows())

        def fill_value_to_rows():
            i = 0
            while i < n:
                j = 0
                while j < m:
                    value_to_rows[grid[i][j]].append(i)
                    j += 1
                i += 1

        fill_value_to_rows()
        memo = {}

        def is_memoized(value_index: int, used_rows_mask: int) -> bool:
            return (value_index, used_rows_mask) in memo

        def get_memoized_value(value_index: int, used_rows_mask: int) -> int:
            return memo[(value_index, used_rows_mask)]

        def set_memoized_value(value_index: int, used_rows_mask: int, value: int):
            memo[(value_index, used_rows_mask)] = value

        def calculate_max_sum(value_index: int, used_rows_mask: int) -> int:
            if value_index > 100:
                return 0
            if is_memoized(value_index, used_rows_mask):
                return get_memoized_value(value_index, used_rows_mask)

            max_sum = dp(value_index + 1, used_rows_mask)

            value_rows = iter(value_to_rows[value_index])
            row = next(value_rows, None)
            while row is not None:
                row_mask = 1 << row
                if (used_rows_mask & row_mask) == 0:
                    max_sum = max(max_sum, value_index + dp(value_index + 1, used_rows_mask | row_mask))
                row = next(value_rows, None)

            set_memoized_value(value_index, used_rows_mask, max_sum)
            return max_sum

        def dp(value_index: int, used_rows_mask: int) -> int:
            return calculate_max_sum(value_index, used_rows_mask)

        return dp(1, 0)

110280