TIL/Algorithm

[99클럽 코테 스터디 21일차 TIL] LeetCode | 1277. Count Square Submatrices with All Ones

ujum 2024. 6. 9. 23:46
728x90

21일차 DP

Problem

https://leetcode.com/problems/count-square-submatrices-with-all-ones/

 

Sol

0과 1로 만들어진 행렬(matrix)에서 1로 만들 수 있는 정사각형의 최대 개수를 구하는 문제

 

 

Dynamic Programming

 

어떤 단계에 있을 때 처음부터 여기에 어떻게 왔는지는 중요하지 않다.

바로 그 앞 단계에서 어떻게 여기까지 왔는지 중요

 

특정 위치 i에 도착해있다고 가정하고  '그럼 그 전에도 어떻게든 알아서 잘 왔겠지' 라는 생각으로 푸는 형식입니다.

 

 

🌱 참고

Dynamic Programming lectures

 

Dynamic Programming lectures

 

www.youtube.com

문제는 짧은데 생각해내는데 너무 오래걸려서 냅다 유튜브로 DP 시청해버렸습니다. 머리아파요

 

 

 

 

해결 방법

👀 현재 위치가 1이라면, 현재 위치의 주변(왼쪽, 위쪽, 왼쪽 위 대각선)에 만들 수 있는 정사각형이 있나 살핍니다. (니가 하면 나도 한다는 마인드)

출처 : 나무위키-무한도전

 

 

 오늘 문제는 그림을 그려서 완벽하게 이해하고 넘어가야 다음에 DP 문제를 풀때도 좋을 것 같아서 그림으로 그려보았습니다. 제가 이해하기 쉽게 그린 것이라 오류가 있다면 알려주세요.. matrix의 값이 1일 경우 주변을 살피고 dp에 값을 업데이트 하는 것을 반복합니다. Input은 다음과 같습니다.

Input: matrix =
[
  [0,1,1,0],
  [1,1,1,1],
  [0,0,1,0]
]

 

 

DP 준비 과정

[1] Input matrix와 초기 dp 상태

 

  1. matrix의 row, col 의 수 구하기

  2. dp[rows][cols] : 주어진 matrix와 같은 크기의 행렬 0으로 초기화
    ⭐ 현재 위치 matrix[i][j]에서 왼쪽, 위쪽, 왼쪽 위 대각선을 보았을 때 만들 수 있는 정사각형의 개수를 저장하는 용도

 

 

matrix[i][j]의 값이 1일 경우 dp에 count

 

3. 첫번째 행 혹은 열일 경우 왼쪽과 위쪽이 없으므로 dp[i][j] = 1

4. 그렇지 않은 경우, 왼쪽 위쪽 왼쪽 위 대각선의 최솟값에 +1

 

 

 

 현재 위치는 (i,j) 입니다. matrix에서 주변 친구가 0이라면 정사각형을 만들 수 없습니다. dp에서도 주변의 최솟값이 0이기 때문에 최솟값+1 해도 원래 값 그대로 1밖에 하지 못합니다. 하지만 주변 친구가 모두 작은 정사각형이라면 나는 더 큰 정사각형이 될 수 있습니다 .

 

 

반복 · · ·

 

5. 위의 과정을 반복해 저장된 dp[rows][cols]의 값을 모두 더해주면, 최대로 만들 수 있는 정사각형 개수를 구할 수 있습니다.

 

 

 


✔ Answer

class Solution:
    def countSquares(self, matrix: List[List[int]]) -> int:
        # 1로 정사각형 만들 수 있는 최대 개수 구하기
        # side 1 인거부터 주위에 만들 수 있는 정사각형있나 살피기(왼, 위, 왼대각) : dp에 개수 저장
        rows, cols = len(matrix), len(matrix[0])
        
        # 각 셀에서 끝나는 정사각형 부분 행렬의 최대 크기를 저장
        # dp = [[0]*cols for _ in range(rows)]
        dp = []
        for _ in range(rows):
            row = [0] * cols
            dp.append(row)
        
        max_squares = 0
        
        for i in range(rows):
            for j in range(cols):
                if matrix[i][j] == 1:
                    # 첫번째 행 or 첫번째 열
                    if i == 0 or j == 0:
                        dp[i][j] = 1
                    # 왼쪽, 위쪽, 왼쪽 위 대각선 최소값에 + 1
                    else:
                        dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1
                    max_squares += dp[i][j]
                
        return max_squares






💬 소감

니가 하면 나도 한다! 니가 안하면 나도 안함