
메모리: 46928 KB, 시간: 1348 ms
다이나믹 프로그래밍
랜드 씨는 퇴직금으로 땅을 사서 목장을 지으려 한다. 그가 사려고 소개받은 땅은 직사각형이고 대부분 들판이지만, 여기저기에 베기 어려운 나무와 치울 수 없는 바위가 있다.
그는 목장을 하나의 정사각형으로 최대한 크게 지으려 하는데, 그 안에 나무나 바위는 없어야 한다.
땅의 세로 길이가 M미터, 가로 길이가 N미터일 때, 1미터 간격의 격자로 된 땅의 지도를 M x N행렬로 표현하자.
이때, 행렬의 원소 0은 들판, 1은 나무 그리고 2는 돌을 의미한다. 랜드씨의 땅에서 지을 수 있는 가장 큰 정사각형 목장의 한 변의 크기 L을 출력하시오.
M N M x N 행렬
L
1X1부터 까지 크기를 늘려가면서 탐색한다.
1. 기준이 될 왼쪽 위의 한 점을 구하고, 장애물이 나오기 전까지 늘려나간다.
2. 장애물이 나오지 않는 가장 최대의 값을 해당 그리드에 모두 메모이제이션 한다.
3. 메모이제이션 값이 0이 아니라면 해당 크기부터 시작하고, 빈 그리드를 채운다
구현이 이렇게 복잡하지 않을건데 싶어서 다른 아이디어를 떠올림.
M x N 행렬을 입력받습니다.
크기 L을 초기값 0으로 설정.
다이나믹 프로그래밍 배열 dp를 생성합니다. dp[i][j]는 (i, j) 위치에서 시작하는 가장 큰 정사각형의 한 변의 길이를 나타낸다.
재귀 함수를 구현합니다. 함수 findLargestSquare(x, y)는 (x, y) 위치에서 시작하는 가장 큰 정사각형의 한 변의 길이를 반환한다:
top = findLargestSquare(x-1, y) # 위쪽 위치에서 시작하는 정사각형의 한 변의 길이left = findLargestSquare(x, y-1) # 왼쪽 위치에서 시작하는 정사각형의 한 변의 길이topLeft = findLargestSquare(x-1, y-1) # 대각선 위 위치에서 시작하는 정사각형의 한 변의 길이dp[x][y] = min(top, left, topLeft) + 1 # 현재 위치에서 시작하는 정사각형의 한 변의 길이를 계산하고 메모이제이션return dp[x][y] # 계산 결과 반환모든 위치에서 재귀 함수 findLargestSquare를 호출하여 가능한 가장 큰 정사각형의 한 변의 길이를 계산하고, 최대값 L을 업데이트한다.
최대값 L을 출력한다.
M, N = map(int, input().split())
matrix = []
for _ in range(M):
row = list(map(int, input().split()))
matrix.append(row)
# 다이나믹 프로그래밍 배열 초기화
dp = [[-1] * N for _ in range(M)]
# 재귀 함수를 사용하여 가장 큰 정사각형의 한 변의 길이를 계산
def solve(x, y):
if x < 0 or y < 0:
return 0
if matrix[x][y] == 0:
if dp[x][y] == -1:
top = solve(x-1, y)
left = solve(x, y-1)
topLeft = solve(x-1, y-1)
dp[x][y] = min(top, left, topLeft) + 1
return dp[x][y]
return 0
L = 0
for i in range(M):
for j in range(N):
if matrix[i][j] == 0:
L = max(L, solve(i, j))
print(L)
아이디어는 금방 생각했는데 구현이 잘 안됐었다. 밖에서 for문을 돌면서 해당 지점부터 크기를 저장하는 방식을 사용하였다.