# 실패한 방법

N,M = map(int,input().split())

arr = [list(map(int,list(input()))) for _ in range(N)]
result = 0
max_size = min(N,M)

for x in range(N):
    for y in range(M):
        if result == max_size:
            break
        if arr[x][y] == 1:
            for sizes in range(result,max_size+1):
                temp = 0
                for dx in range(sizes):
                    for dy in range(sizes):
                        if 0<=x+dx<N and 0<=y+dy<M: 
                            temp += arr[x+dx][y+dy]
                if temp == sizes**2:
                    result = sizes
                else:
                    break
print(result**2)

처음에 단순하게 현재의 max_size만큼을 각 위치에서 탐색을 해서 갱신해주는 방식을 했다. 이렇게 하니 시간 초과가 나왔다.

 

N,M = map(int,input().split())
arr = [[0]*(M+1)]
for _ in range(N):
    arr.append([0]+list(map(int,list(input()))))
result = 0
max_size = min(N,M)

for x in range(1,N+1):
    for y in range(1,M+1):
        if arr[x][y]:
            arr[x][y] = min(arr[x-1][y],arr[x][y-1],arr[x-1][y-1])+1
            result = max(arr[x][y],result)
        if result == max_size:
            break

print(result**2)
1 1
1 1

위와 같은 정사각형이 있으면,  우하단을 기준으로 상하, 대각선이 전부 1이어야만 정사각형이 모양이된다. 만약 3개 중 하나라도 0이 있으면 크기가 2인 정사각형이 모양이 안된다. 그러므로 여기서 될수 있는 정사각형의 크기는 2이다.

 

1 1
1 2

이걸 좀 더 확장해서 3*3를 그려보도록 하자.

1 1 1
1 1 1
1 1 1

위와 같이 있다고 했을때 행과 열 중 0인 곳은 크기가 1를 초과하는 것을 못 만드므로 예외로 하겠다. 그러면 실질적으로 1,1 부터 탐색을 한다.

1 1 1
1 2 2
1 2 3

위와 같은 로직으로 하면 다음과 같이 우하단이 3이 되는 것을 알 수 있다 

1 1 1
0 1 1
1 1 1

이렇게 한군데가 비어있으면

 

1 1 1
0 1 2
1 1 2

이렇듯 우하단이 2가 되는 것을 알 수 있다.

 

그러므로 이 문제는 (x,y) 좌표 기준으로 (x-1,y),(x,y-1),(x-1,y-1)의 값의 최소값에 + 1을 해주면 된다.

 

그리고 저장된 값 중에서 가장 큰 값이 이 행렬에서 제일 큰 정사각형이므로, 제곱을 해서 출력을 하면 된다.

'알고리즘 > 백준' 카테고리의 다른 글

[BOJ/백준] 5557 1학년  (0) 2021.02.16
[BOJ/백준] 2493 탑  (0) 2021.02.16
[BOJ/백준] 2225 합분해  (0) 2021.02.16
[BOJ/백준] 3190 뱀  (0) 2021.02.16
[BOJ/백준] 10026 적록색약  (0) 2021.02.16

+ Recent posts