<p>You are given an <code>m x n</code> binary matrix <code>grid</code>.</p>

<p>A row or column is considered <strong>palindromic</strong> if its values read the same forward and backward.</p>

<p>You can <strong>flip</strong> any number of cells in <code>grid</code> from <code>0</code> to <code>1</code>, or from <code>1</code> to <code>0</code>.</p>

<p>Return the <strong>minimum</strong> number of cells that need to be flipped to make <strong>all</strong> rows and columns <strong>palindromic</strong>, and the total number of <code>1</code>&#39;s in <code>grid</code> <strong>divisible</strong> by <code>4</code>.</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,0,0],[0,1,0],[0,0,1]]</span></p>

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

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

<p><img src="https://assets.leetcode.com/uploads/2024/08/01/image.png" style="width: 400px; height: 105px;" /></p>
</div>

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

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

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

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

<p><img alt="" src="https://assets.leetcode.com/uploads/2024/07/08/screenshot-from-2024-07-09-01-37-48.png" style="width: 300px; height: 104px;" /></p>
</div>

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

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

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

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

<p><img alt="" src="https://assets.leetcode.com/uploads/2024/08/01/screenshot-from-2024-08-01-23-05-26.png" style="width: 200px; height: 70px;" /></p>
</div>

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

<ul>
	<li><code>m == grid.length</code></li>
	<li><code>n == grid[i].length</code></li>
	<li><code>1 &lt;= m * n &lt;= 2 * 10<sup>5</sup></code></li>
	<li><code>0 &lt;= grid[i][j] &lt;= 1</code></li>
</ul>


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

        def cost(a, b, c, d):
            ret = 0
            
            if (a, b) == (0, 0):
                if (c, d) == (0, 0):
                    ret += 0
                elif (c, d) == (0, 1):
                    ret += 1
                elif (c, d) == (1, 0):
                    ret += 1
                else:
                    ret += 2
                    
            elif (a, b) == (0, 1):
                if (c, d) == (0, 0):
                    ret += 1
                elif (c, d) == (0, 1):
                    ret += 2
                elif (c, d) == (1, 0):
                    ret += 2
                else:
                    ret += 1
                    
            elif (a, b) == (1, 0):
                if (c, d) == (0, 0):
                    ret += 1
                elif (c, d) == (0, 1):
                    ret += 2
                elif (c, d) == (1, 0):
                    ret += 2
                else:
                    ret += 1
                    
            elif (a, b) == (1, 1):
                if (c, d) == (0, 0):
                    ret += 2
                elif (c, d) == (0, 1):
                    ret += 1
                elif (c, d) == (1, 0):
                    ret += 1
                else:
                    ret += 0
            return ret
                    
        ret = 0
        si = 0
        oi = 0
        
        def dp(l, r):
            nonlocal ret, si, oi

            if r < l:
                return 
            if r == l:
                for i in range((n + 1) // 2):
                    if i == n - i - 1:
                        if grid[i][l] == 1: # SINGLE
                            ret += 1
                        break
                    else:
                        if grid[i][l] == grid[n - i - 1][l]:
                            if grid[i][l] == 1:
                                si += 1
                        else:
                            oi += 1
                            ret += 1
                return

            for i in range((n + 1) // 2):
                if i == n - i - 1:
                    if grid[i][l] == grid[n - i - 1][r]:
                        if grid[i][l] == 1:
                            si += 1
                    else:
                        oi += 1
                        ret += 1
                    break
                a = grid[i][l]
                b = grid[i][r]
                c = grid[n - i - 1][l]
                d = grid[n - i - 1][r]
                ret += cost(a, b, c, d)
            dp(l + 1, r - 1)
            
        dp(0, m - 1)
        rem = si % 2
        if rem:
            ret += max(0, (rem - oi)) * 2
        return ret
75600