백준 4095 최대 정사각형

김민형·2022년 1월 12일

문제설명

접근방식

0과 1로 구성된 배열 정보를 통해서 1들로만 구성된 최대 정사가형의 너비 혹은 높이를 찾아주는 문제이다. 예제에 나와있는 배열을 그려가면서 정사각형을 찾다보면 문제의 핵심은 정사각형이라는 점을 이해할 수 있다. 만약 문제의 제시가 직사각형이었으면 훨씬 더 문제풀이가 복잡해질 수 있으나 문제에서 요구하는 것은 정사각형이기 때문에 상대적으로 쉽게 접근할 수 있다.

한 모서리를 기준으로 정사각형을 카운트하게 되면 간단하게 접근할 수 있다. 우측하단 모서리를 기준으로 정사각형의 최대 크기를 구한다고 했을 때 그 크기는 우,상단 방향의 3점들에서 얻은 값을 바탕으로 구할 수 있다. (i,j)의 포인트에서 정사각형의 최대너비를 구하다고 했을 때 (i, j-1,) , (i-1, j-1), (i-1, j)의 세 점을 기준으로 얻을 수 있는 정사각형의 공통최소너비에 1을 더한 값이 되게 된다. (i,j) 포인트에서의 최대 정사각형의 너비를 x라고 했을 때 (i-x+1, j), (i-x+!, j-x+1), (i,j-x+1), (i, j)의 네 모서리를 가지는 지점이고 이는 앞서 말한 세 지점에서 X-1의 너비를 가지면서 그 안에 속해있어야만 한다.


다음과 같은 방식으로 x-1 너비의 3개의 정사각형과 1너비의 정사각형이 하나가 만나서 x너비의 정사각형을 구성하게 된다.

if(arr[i][j]){
   dp[i][j] = min(dp[i-1][j], dp[i-1][j-1], dp[i][j-1]) + 1;
}
// dp[i][j]는 (i,j) 구할 수 있는 정사각형의 최대 너비 

C++ 코드

#include <bits/stdc++.h>

using namespace std;
using ll = long long;
using pii = pair <ll, ll>;

int main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

  //freopen("inp.txt", "r", stdin);
  
  int N, M;
  while(1){
    cin >> N >> M;
    if(N==0 && M==0)
      break;
    
    vector<vector<int>> arr(N+1, vector<int>(M+1));
    vector<vector<int>> dp(N+1, vector<int>(M+1, 0));
    int ans = 0;
    for(int i=1; i<=N; i++){
      for(int j=1; j<=M; j++){
        cin >> arr[i][j];
        if(arr[i][j]){
          dp[i][j] = 1;
          dp[i][j] += min(dp[i-1][j-1],min(dp[i][j-1], dp[i-1][j]));
        }
        ans = max(ans, dp[i][j]);
      }
    }
    cout << ans << '\n';
  }
}
profile
천천히 성장하는 프론트 개발자

0개의 댓글