티스토리 뷰

 

문제 링크 : https://www.acmicpc.net/problem/1915

 

1915번: 가장 큰 정사각형

첫째 줄에 n, m(1 ≤ n, m ≤ 1,000)이 주어진다. 다음 n개의 줄에는 m개의 숫자로 배열이 주어진다.

www.acmicpc.net

 

 

각각의 i, j 에서 변의 길이 \( l \) 을 이용하여 loop 를 돌리면 시간 복잡도는 \( O(n^4) \) 이 된다.

2차원 부분합을 미리 구했다면  \(O(n^3)\) 으로 해결할 수 있지만 시간 초과일 것이다.

 

앞 단계에서 최대 정사각형을 찾기 위해 조사한 것을 재활용할 수 있음을 깨닫게 되면 DP 풀이는 쉽다.

 

우선 문자열 2차원 배열을 정수 2차원 배열 grid 에  저장했다고 가정한다. 

그리고, dp[i][j] 를 i , j 가 정사각형의 우측하단이 되는 최대의 정사각형의 값 k>0 라 하자.

(이때, grid[i][j]==1 일 것이다.)

그렇다면 dp[i-1][j-1] 은 k-1 이어야 할 것이고 dp[ i-1][j] , dp[i][j-1] 은 k-1 이상일 것이다.

이를 정리하면  grid[i][j]==1 일 때, 다음의 점화식이 성립한다.

 

dp[i][j] = 1 + min( dp[i-1][j-1] , dp[i-1][j], dp[i][j-1] )

 

이제는 루틴이다.

 

#include<bits/stdc++.h>

using namespace std;

int n,m,grid[1001][1001],dp[1001][1001];
char str[1001][1001];

int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++){
        scanf("%s",str[i]);
        for(int j=0;j<m;j++){
            int x=str[i][j]-'0';
            grid[i+1][j+1]=dp[i+1][j+1]=x;
        }
    }
    
    int ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(!grid[i][j])continue;
            dp[i][j]=min(dp[i-1][j-1], min(dp[i-1][j], dp[i][j-1]))+1;
            ans=max(ans, dp[i][j]);
        }
    }
    printf("%d\n", ans*ans);
}

 

 

최소값을 관리하는 2차원 세그먼트 트리를 사용하면 \( O(n^2 \log^2(n))\) 으로 해결할 수 있지만 생략한다.

 

 

반응형

'DS\Algo > Dynamic Programming' 카테고리의 다른 글

BOJ 17070 파이프 옮기기 1  (2) 2022.09.19
BOJ 10942 팰린드롬?  (0) 2022.09.17
BOJ 11066 Merging Files(파일 합치기)  (0) 2022.09.14
BOJ 11048 이동하기  (0) 2022.09.11
BOJ 11054 가장 긴 바이토닉 부분 수열  (0) 2022.09.09
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함