본문 바로가기

알고리즘 관련/Programmers

가장 큰 정사각형

가장 단순하게 생각해 볼 수 있는 방법은 특정 좌표가 1이라면, 가능한 정사각형들을 반복문을 돌면서 하나씩 탐색해보는 방법이다.

이해를 돕기 위해 함수로 표현하면 다음과 같다.

//size : 정사각형의 변의 길이
bool IsPossible(int row, int col, int size)
{
	for(int i = row; i < row + size; i++){
    		for(int j = col; j < col + size; j++){
              	if(board[i][j] == 0){
                  	return false;
              	}
        }
    }
    return true;
}

그러나 이 방법으로는 효율성 부분을 통과할 수 없었다.

 

두 번째 방법으로 가장 큰 정사각형을 찾는게 답이기 때문에 지금까지 계산했었던 가장 큰 변의 길이로 계산하는 방법이었다. 그러나 이것도 효율성에서 실패했었다.

 

세 번째 방법은 DP의 개념을 응용해야 하는데, 길이가 W인 정사각형을 만드는데에 W - 1인 정사각형을 만드는 경우가 부분문제로 포함된다. 

//사각형의 오른쪽 하단 기준, 좌표 (i, j)를 포함하여 만들 수 있는 가장 큰 정사각형의 길이
dp[i][j] = min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1])

 

이해를 돕기 위해, 길이가 3인 정사각형을 DP방식으로 구해보면 테이블은 다음과 같다.

1 1 1
1 2 2
1 2 3

길이가 2인 정사각형은 사각형의 오른쪽 하단 값 1을 기준으로 위쪽, 왼쪽, 왼쪽 대각선이 모두 1이여야 한다.

마찬가지로 길이가 3인 정사각형은 오른쪽 하단 값 1을 기준으로 위쪽, 왼쪽, 왼쪽 대각선이 모두 1이여야 하는데, 앞에서 미리 구해놓은 길이 2인 정사각형의 값을 이용하는 것이다!

정답코드

더보기
#include <iostream>
#include<vector>
#include <algorithm>
using namespace std;
#define MAX_SIZE 1000
int width, height;

int solution(vector<vector<int>> board)
{
    int answer = 0;
    int MaxSize = 0;
    //dp[W][H] = 오른쪽 하단 기준, 가장 큰 정사각형의 변의 길이
    height = board.size();
    width = board[0].size();
    if(height == 1 || width == 1)
        return 1;
    for(int i = 1; i < height; i++){
        for(int j = 1; j < width; j++){
            if(board[i][j] == 1){
                board[i][j] = min(board[i - 1][j - 1], 
                              min(board[i][j - 1], board[i - 1][j])) + 1;
                MaxSize = max(MaxSize, board[i][j]);
            }
        }
    }
    answer = MaxSize * MaxSize;
    return answer;
}

'알고리즘 관련 > Programmers' 카테고리의 다른 글

합승 택시 요금  (0) 2021.03.02
소수 만들기  (0) 2021.02.16
구명보트  (0) 2021.02.08
가장 큰 수 만들기  (0) 2021.02.05
다리를 지나는 트럭  (0) 2021.02.01