Imagine you're a digital artist working with a special painting grid! You start with an n ร n white canvas and have a unique brush that can paint entire columns from top to bottom.
Here's how your magical brush works: when you select any cell at position (i, j), it colors all cells black in column j from the top row (row 0) down to row i inclusive.
The scoring system is fascinating: You earn points equal to the value of each white cell that has at least one horizontally adjacent black cell (left or right neighbor).
Your mission: Maximize your total score by strategically choosing which cells to paint!
Input: A 2D matrix grid of size n ร n containing positive integers Output: The maximum possible score you can achieve
Input & Output
example_1.py โ Basic Example
$Input:grid = [[1,1,1],[1,1,1],[1,1,1]]
โบOutput:4
๐ก Note:Paint column 1 completely (height 3). This creates white cells at positions (0,0), (1,0), (2,0), (0,2), (1,2), (2,2) with black horizontal neighbors. Each contributes score 1, but we only count horizontal adjacencies, giving us a score of 4.
example_2.py โ Strategic Painting
$Input:grid = [[2,3,4],[5,6,7],[8,9,1]]
โบOutput:22
๐ก Note:Optimal strategy involves painting column 0 to height 2 and column 1 to height 1. This creates strategic boundaries that maximize the sum of white cells with black neighbors.
example_3.py โ Single Column Edge Case
$Input:grid = [[5]]
โบOutput:0
๐ก Note:With only one column, no cell can have a horizontal neighbor, so the maximum score is 0.
Constraints
1 โค n โค 100
1 โค grid[i][j] โค 105
The grid is always square (n ร n)
Time limit: 3 seconds
Visualization
Tap to expand
Understanding the Visualization
1
Choose Painting Heights
For each column, decide how far down to paint (0 to n rows)
2
Create Boundaries
White-black boundaries form horizontally between adjacent columns
3
Calculate Score
Sum values of white cells that have black horizontal neighbors
4
Optimize Configuration
Use DP to find the height combination that maximizes total score
Key Takeaway
๐ฏ Key Insight: The optimal solution balances creating valuable boundaries while maximizing the sum of white cells adjacent to black regions through strategic column height selection.
The optimal solution uses Dynamic Programming with state dp[col][height] representing maximum score for columns 0 to col where column col is painted to the given height. Key insight: only horizontal boundaries between white and black cells contribute to the score. Time complexity: O(nยณ), Space: O(nยฒ).
Common Approaches
Approach
Time
Space
Notes
โ
Dynamic Programming with Memoization
O(nยณ ร 2^n)
O(n ร 2^n)
Use memoization to avoid recalculating scores for repeated subproblems
Optimized Dynamic Programming (Optimal)
O(nยณ)
O(nยฒ)
Use state-space DP considering column interdependencies for optimal scoring
Brute Force (Try All Configurations)
O(n^(n+2))
O(nยฒ)
Try every possible painting height for each column and calculate the maximum score
Dynamic Programming with Memoization โ Algorithm Steps
Create a memoization table indexed by column and previous column's state
For each column, try all possible painting heights (0 to n)
Calculate the contribution of current column given previous column's height
Recursively solve for remaining columns with memoization
Return the maximum score achievable
Visualization
Tap to expand
Step-by-Step Walkthrough
1
State Representation
Each node represents (column, heights_so_far)
2
Memoization Check
Check if this state was already computed
3
Recursive Exploration
Try all heights for current column if not memoized
4
Store Result
Cache the result for future use
Code -
solution.c โ C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_MEMO 10000
typedef struct {
char key[200];
int value;
} MemoEntry;
MemoEntry memo[MAX_MEMO];
int memoSize = 0;
int findMemo(const char* key) {
for (int i = 0; i < memoSize; i++) {
if (strcmp(memo[i].key, key) == 0) {
return memo[i].value;
}
}
return -1;
}
void addMemo(const char* key, int value) {
if (memoSize < MAX_MEMO) {
strcpy(memo[memoSize].key, key);
memo[memoSize].value = value;
memoSize++;
}
}
int calculateFullScore(int** grid, int* heights, int n) {
bool** painted = (bool**)malloc(n * sizeof(bool*));
for (int i = 0; i < n; i++) {
painted[i] = (bool*)calloc(n, sizeof(bool));
}
for (int col = 0; col < n; col++) {
for (int row = 0; row < heights[col]; row++) {
painted[row][col] = true;
}
}
int score = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (!painted[i][j]) {
bool hasBlackNeighbor = false;
if (j > 0 && painted[i][j-1]) hasBlackNeighbor = true;
if (j < n-1 && painted[i][j+1]) hasBlackNeighbor = true;
if (hasBlackNeighbor) {
score += grid[i][j];
}
}
}
}
for (int i = 0; i < n; i++) {
free(painted[i]);
}
free(painted);
return score;
}
int dp(int** grid, int col, int* heightsSoFar, int heightsCount, int n) {
if (col == n) {
return calculateFullScore(grid, heightsSoFar, n);
}
char key[200];
sprintf(key, "%d,", col);
for (int i = 0; i < heightsCount; i++) {
char temp[10];
sprintf(temp, "%d,", heightsSoFar[i]);
strcat(key, temp);
}
int memoResult = findMemo(key);
if (memoResult != -1) {
return memoResult;
}
int maxScore = 0;
for (int height = 0; height <= n; height++) {
heightsSoFar[heightsCount] = height;
int score = dp(grid, col + 1, heightsSoFar, heightsCount + 1, n);
if (score > maxScore) {
maxScore = score;
}
}
addMemo(key, maxScore);
return maxScore;
}
int maxScoreFromGridOperations(int** grid, int gridSize, int* gridColSize) {
memoSize = 0;
int* heights = (int*)malloc(gridSize * sizeof(int));
int result = dp(grid, 0, heights, 0, gridSize);
free(heights);
return result;
}
Time & Space Complexity
Time Complexity
โฑ๏ธ
O(nยณ ร 2^n)
n columns, nยฒ possible states per column, up to 2^n unique subproblems
n
2n
โ Quadratic Growth
Space Complexity
O(n ร 2^n)
Memoization table storing results for each column and state combination
n
2n
โ Quadratic Space
25.0K Views
MediumFrequency
~15 minAvg. Time
850 Likes
Ln 1, Col 1
Smart Actions
๐กExplanation
AI Ready
๐ก SuggestionTabto acceptEscto dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen
Algorithm Visualization
Pinch to zoom โข Tap outside to close
Test Cases
0 passed
0 failed
3 pending
Select Compiler
Choose a programming language
Compiler list would appear here...
AI Editor Features
Header Buttons
๐ก
Explain
Get a detailed explanation of your code. Select specific code or analyze the entire file. Understand algorithms, logic flow, and complexity.
๐ง
Fix
Automatically detect and fix issues in your code. Finds bugs, syntax errors, and common mistakes. Shows you what was fixed.
๐ก
Suggest
Get improvement suggestions for your code. Best practices, performance tips, and code quality recommendations.
๐ฌ
Ask AI
Open an AI chat assistant to ask any coding questions. Have a conversation about your code, get help with debugging, or learn new concepts.
Smart Actions (Slash Commands)
๐ง
/fix Enter
Find and fix issues in your code. Detects common problems and applies automatic fixes.
๐ก
/explain Enter
Get a detailed explanation of what your code does, including time/space complexity analysis.
๐งช
/tests Enter
Automatically generate unit tests for your code. Creates comprehensive test cases.
๐
/docs Enter
Generate documentation for your code. Creates docstrings, JSDoc comments, and type hints.
โก
/optimize Enter
Get performance optimization suggestions. Improve speed and reduce memory usage.
AI Code Completion (Copilot-style)
๐ป
Ghost Text Suggestions
As you type, AI suggests code completions shown in gray text. Works with keywords like def, for, if, etc.
Tabto acceptEscto dismiss
๐ฌ
Comment-to-Code
Write a comment describing what you want, and AI generates the code. Try: # two sum, # binary search, # fibonacci
๐ก
Pro Tip: Select specific code before using Explain, Fix, or Smart Actions to analyze only that portion. Otherwise, the entire file will be analyzed.