You are given four integers, m
, n
, introvertsCount
, and extrovertsCount
. You have an m x n
grid, and there are two types of people: introverts and extroverts. There are introvertsCount
introverts and extrovertsCount
extroverts.
You should decide how many people you want to live in the grid and assign each of them one grid cell. Note that you do not have to have all the people living in the grid.
The happiness of each person is calculated as follows:
120
happiness and lose 30
happiness for each neighbor (introvert or extrovert).40
happiness and gain 20
happiness for each neighbor (introvert or extrovert).Neighbors live in the directly adjacent cells north, east, south, and west of a person's cell.
The grid happiness is the sum of each person's happiness. Return the maximum possible grid happiness.
Example 1:
Input: m = 2, n = 3, introvertsCount = 1, extrovertsCount = 2 Output: 240 Explanation: Assume the grid is 1-indexed with coordinates (row, column). We can put the introvert in cell (1,1) and put the extroverts in cells (1,3) and (2,3). - Introvert at (1,1) happiness: 120 (starting happiness) - (0 * 30) (0 neighbors) = 120 - Extrovert at (1,3) happiness: 40 (starting happiness) + (1 * 20) (1 neighbor) = 60 - Extrovert at (2,3) happiness: 40 (starting happiness) + (1 * 20) (1 neighbor) = 60 The grid happiness is 120 + 60 + 60 = 240. The above figure shows the grid in this example with each person's happiness. The introvert stays in the light green cell while the extroverts live on the light purple cells.
Example 2:
Input: m = 3, n = 1, introvertsCount = 2, extrovertsCount = 1 Output: 260 Explanation: Place the two introverts in (1,1) and (3,1) and the extrovert at (2,1). - Introvert at (1,1) happiness: 120 (starting happiness) - (1 * 30) (1 neighbor) = 90 - Extrovert at (2,1) happiness: 40 (starting happiness) + (2 * 20) (2 neighbors) = 80 - Introvert at (3,1) happiness: 120 (starting happiness) - (1 * 30) (1 neighbor) = 90 The grid happiness is 90 + 80 + 90 = 260.
Example 3:
Input: m = 2, n = 2, introvertsCount = 4, extrovertsCount = 0 Output: 240
Constraints:
1 <= m, n <= 5
0 <= introvertsCount, extrovertsCount <= min(m * n, 6)
This problem involves finding the optimal arrangement of introverts and extroverts in a grid to maximize their total happiness. The happiness of each individual depends on their neighbors. The solution uses dynamic programming with memoization to efficiently explore the state space.
Key Ideas:
State Representation: The core idea is representing the grid state efficiently. Since each cell can be empty, have an introvert, or have an extrovert, a ternary number system is used. Each row is represented as a base-3 number, where 0 means empty, 1 means introvert, and 2 means extrovert. This allows for concise representation and traversal of the search space.
Memoization: To avoid redundant computations, dynamic programming with memoization is used. The dfs
function stores previously computed results to avoid recalculating them.
Transition Calculation: The dfs
function calculates the happiness for each possible state transition. It considers the current row's configuration and its effect on the happiness of the current individuals and their interaction with the neighbors (above and to the left).
Base Cases: The base cases for the dfs
function are when all rows are filled or when all people are placed.
Time Complexity Analysis:
Solution 1 (Ternary State Compression): The time complexity is O(32n * (m * ic * ec + n)). The 3n represents the possible states for a single row, and 3n again for the previous row. The (m * ic * ec + n) factor comes from iterating through rows, people, and columns respectively during the recursive calls.
Solution 2 (Contour Line Memorized Search): The time complexity is O(3n+1 * m * n * ic * ec). This solution explores states cell by cell. The 3n+1 comes from the possible states of the current cell and its neighbors. The rest (m * n * ic * ec) factor represents iterations during the recursive calls.
Space Complexity Analysis:
Solution 1: O(32n + 3n * m * ic * ec). The first part is from the memoization table, and the second from the space used by the other variables during the recursion.
Solution 2: O(3n * m * n * ic * ec). This is dominated by the size of the memoization table.
Code Explanation (Python3 - Solution 1):
class Solution:
def getMaxGridHappiness(self, m, n, introvertsCount, extrovertsCount):
@cache # This is a Python decorator for memoization
def dfs(i, pre, ic, ec):
# Base Cases
if i == m or (ic == 0 and ec == 0):
return 0
ans = 0
for cur in range(mx): # Iterate through possible row states
if ix[cur] <= ic and ex[cur] <= ec: # Check constraints (enough people left)
ans = max(ans, f[cur] + g[pre][cur] + dfs(i + 1, cur, ic - ix[cur], ec - ex[cur]))
return ans
# Preprocessing: Calculate happiness contributions and counts
mx = 3**n
f = [0] * mx
g = [[0] * mx for _ in range(mx)]
# ... (rest of the preprocessing which calculates f and g, as shown in the original response)...
return dfs(0, 0, introvertsCount, extrovertsCount)
The code first preprocesses to compute f
(initial happiness of each row state) and g
(interaction happiness between adjacent rows). Then the recursive dfs
function efficiently explores all possible states, using memoization to speed up the process. The base cases handle situations where all rows are filled or all people are placed.
The Java, C++, and TypeScript solutions follow a similar structure, utilizing memoization and optimized state representations to solve the problem efficiently. They differ slightly in syntax and data structure handling but share the core dynamic programming logic.