본문 바로가기

코딩 테스트(Coding test)/Lv. 2

[프로그래머스/C++] 가장 큰 정사각형 찾기

미숙한 블로그 주인이 코딩테스트 문제를 풀어가는 과정을 담은 글입니다. 이 풀이가 효율적인 풀이가 아닐 수 있으며, 부정확한 정보가 많이 있을 수 있습니다. 보완해야할 점이 있다면 댓글로 남겨주세요!

 

https://programmers.co.kr/learn/courses/30/lessons/12905#

 

코딩테스트 연습 - 가장 큰 정사각형 찾기

[[0,1,1,1],[1,1,1,1],[1,1,1,1],[0,0,1,0]] 9

programmers.co.kr

가장 큰 정사각형 찾기

문제

1와 0로 채워진 표(board)가 있습니다. 표 1칸은 1 x 1 의 정사각형으로 이루어져 있습니다. 표에서 1로 이루어진 가장 큰 정사각형을 찾아 넓이를 return 하는 solution 함수를 완성해 주세요. (단, 정사각형이란 축에 평행한 정사각형을 말합니다.)

예를 들어

0 1 1 1
1 1 1 1
1 1 1 1
0 0 1 0

가 있다면 가장 큰 정사각형은

0 1 1 1
1 1 1 1
1 1 1 1
0 0 1 0

가 되며 넓이는 9가 되므로 9를 반환해 주면 됩니다.

제한사항

  • 표(board)는 2차원 배열로 주어집니다.
  • 표(board)의 행(row)의 크기 : 1,000 이하의 자연수
  • 표(board)의 열(column)의 크기 : 1,000 이하의 자연수
  • 표(board)의 값은 1또는 0으로만 이루어져 있습니다.

 

풀이

입출력 예시

 

풀이

규칙만 알면 쉬운 문제이지만, 규칙을 찾는 것이 매우 어려운 문제이다. 동적 프로그래밍을 알아야 풀 수 있는 문제이기도 했다.

(그건 다 그렇잖아)

 

규칙

 

board가 아래 그림과 같이 주어졌다고 하자.

 

 

규칙은 아래 그림과 같다. 2x2 칸의 정사각형에서 4개의 원소가 모두 1이 아닐 때, (i+1, j+1)의 위치의 값을 갱신한다. 갱신하는 방법은, (i+1, j+1) 위치의 값을 제외한 값들에서 최솟값을 구한 뒤, 그 값 +1로 갱신시킨다. 이 과정을 처음부터 반복하고 최댓값을 구한 뒤, 제곱해주면 구하고자 하는 문제의 답이 나온다.

 

 

#include <vector>
#include <algorithm>

using namespace std;

int min(int a, int b, int c) {
    int min_v;
    
    min_v = min(a, b);
    min_v = min(min_v, c);
    
    return min_v;
}

int solution(vector<vector<int>> board) {
    int answer = *max_element(board[0].begin(), board[0].end());
    int low = board[0].size();
    int height = board.size();
    vector<vector<int>> memo = board;
    
    for (int i = 0; i < height - 1; i++) {       
        for (int j = 0; j < low - 1; j++) {
            if (board[i][j] != 0 && board[i][j + 1] != 0 && board[i + 1][j] != 0 && board[i + 1][j + 1]) {
                memo[i + 1][j + 1] = min(memo[i][j], memo[i][j + 1], memo[i + 1][j]) + 1;
                answer = max(memo[i + 1][j + 1], answer);
            }
        }
    }

    answer *= answer;

    return answer;
}