Search
Duplicate

가장 큰 정사각형

주차
11주차
문제번호
1915
언어
티어
골드
유형
DP
nj_Blog
nj_상태
이해도
풀이
사람
이해도 2
13 more properties

Memo

접근 방법
이차원 배열에 값을 저장해 놓습니다. 가로 세로 길이를 1씩 증가시킨 상태여야 하는데 그 이유는 코드의 일관성 때문입니다. 처음에 배열을 0으로 초기화 합니다. 그 후에 1,1 부터 N,N 까지 input을 받습니다.
1,1 부터 N,N 까지 각 행마다 각 열을 순회하는데, 현재 자신의 위치의 값이 0이라면 정사각형은 절때 만들어 질 수 없기 때문에 그 곳은 분기를 통해 지나치고, 현재 자신의 위치의 값이 1이라면 위, 왼쪽 위 대각선, 왼쪽을 검사하여 가장 작은 값에 1을 더한 값 을 저장합니다.
가장 작은 값을 선택하는 이유는, 현재 그 자리에 그 값이 왜 있는지를 생각해 보면 되는데, 조사하려고 하는 그 자리에 있는 값은 0을 만났을 때를 제외한 자신이 만들수 있는 가장 긴 길이의 정사각형 한 변이기 때문입니다. 따라서 그 변은 확정적으로 자신의 현재 위치에서 만들 수 있는 것입니다.
가장 긴 변을 순회하면서 계속해서 업데이트를 해나가면서, 최종적으로 가장 큰 정사각형의 넓이를 구해낼 수 있습니다.

Code

제출 날짜

@2/24/2021

메모리

5996 KB

시간

12 ms
#include <iostream> #include <vector> #include <algorithm> std::vector<std::vector<int> > sq; size_t n, m; int g_max; void input_faster() { std::ios_base::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); } void input() { input_faster(); std::string tmp; std::cin >> n >> m; sq.resize(n + 1, std::vector<int>(m+1)); for (size_t i = 1 ; i < n + 1 ; i++) { std::cin >> tmp; for (size_t j = 1 ; j < tmp.size() + 1 ; j++) sq[i][j] = tmp[j - 1] - '0'; } g_max = 0; } void logic() { for (size_t i = 1; i < n + 1 ; i++) for (size_t j = 1 ; j < m + 1 ; j++) { if (!sq[i][j]) continue; sq[i][j] = std::min({sq[i - 1][j], sq[i][j - 1], sq[i - 1][j - 1]}) + 1; g_max = g_max > sq[i][j] ? g_max : sq[i][j]; } } void solve() { logic(); std::cout << g_max * g_max; } int main() { input(); solve(); return (0); }
C++
복사
(+ 추가적으로)
맞은 사람 코드중에서 4ms가 있어서 봤는데, 좀 놀라웠습니다.
A, B 변수가 있는데 각각 0, 1 로 초기화 되어있고 그 값은 swap을 통해 계속해서 바뀌어 가고 있었습니다.
@suhshin 덕분에 코드를 빠르게 파악했는데, 배열의 크기를 n x m 으로 두지 않고, 2 x m으로 두고나서 인풋을 받음과 동시에 누적합을 계산했습니다...
아래 코드는 위 로직을 가지고 작성한 코드입니다.
#include <iostream> #include <vector> #include <algorithm> std::vector<std::vector<int> > sq; size_t n, m; int g_max; int A, B; void input_faster() { std::ios_base::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); } void logic() { input_faster(); std::string tmp; std::cin >> n >> m; sq.resize(2, std::vector<int>(m+1)); A = 0; B = 1; int val_tmp; g_max = 0; for (size_t i = 1 ; i < n + 1 ; i++) { std::cin >> tmp; for (size_t j = 1 ; j < tmp.size() + 1 ; j++) { if (tmp[j - 1] == '0') sq[B][j] = tmp[j - 1] - '0'; else { sq[B][j] = std::min({sq[A][j], sq[B][j - 1], sq[A][j - 1]}) + 1; g_max = g_max > sq[B][j] ? g_max : sq[B][j]; } } val_tmp = A; A = B; B = val_tmp; } } void solve() { logic(); std::cout << g_max * g_max; } int main() { solve(); return (0); }
C++
복사
위 코드의 결과는
처음 작성한 코드의 메모리와 시간에 비해서 월등하게 좋아졌습니다.