1915번: 가장 큰 정사각형
첫째 줄에 n, m(1 ≤ n, m ≤ 1,000)이 주어진다. 다음 n개의 줄에는 m개의 숫자로 배열이 주어진다.
www.acmicpc.net
top-down 방식으로 풀 경우 배열 (y,x)의 값이 1일 경우 가질 수 있는 가장 큰 정사각형 한 변의 길이는 →, ↓, ↘ 방향에 위치한 좌표에서 가질 수 있는 가장 큰 정사각형의 한 변의 길이 중 가장 작은값 + 1 이다. (y,x)의 값이 0일 경우는 정사각형이 만들어질 수 없기 때문에 변의 길이는 0 이다.
bottom-up 방식으로 풀 경우 채워나가는 방향이 반대이기 때문에 탐색 방향을 top-down과 반대로 하면 동일한 결과를 얻을 수 있다.
#include <iostream>
#include <string>
using namespace std;
const int INF = 987654321;
int n, m, map[1001][1001], memo[1001][1001];
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }
int Topdown(int hereY, int hereX)
{
int dy[3] = { 0,1,1 };
int dx[3] = { 1,0,1 };
if (hereY > n || hereX > m) return 0;
if (map[hereY][hereX] == 0) return 0;
int& ret = memo[hereY][hereX];
if (ret != 0) return ret;
ret = 1;
int res = INF;
for (int i = 0; i < 3; i++)
{
int next = Topdown(hereY + dy[i], hereX + dx[i]);
res = min(res, next);
}
return ret += res;
}
int Bottomup()
{
int dy[3] = { 0,-1,-1 };
int dx[3] = { -1,0,-1 };
int res = 0;
for(int i=1; i<=n; i++)
for (int j = 1; j <= m; j++)
{
if (map[i][j] == 0)
memo[i][j] = 0;
else
{
int last = INF;
for (int k = 0; k < 3; k++)
last = min(last, memo[i + dy[k]][j + dx[k]]);
memo[i][j] = map[i][j] + last;
}
res = max(res, memo[i][j]);
}
return res * res;
}
int main(void)
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
string str;
cin >> str;
for (int j = 1; j <= m; j++)
map[i][j] = str[j - 1] - '0';
}
// top-down
int res = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
res = max(res, Topdown(i, j));
cout << res * res << endl;
// bottom-up
cout << Bottomup() << endl;
return 0;
}
알고리즘 200일 프로젝트 - 92 day
'알고리즘 > BOJ' 카테고리의 다른 글
백준 2096번: 내려가기 (0) | 2020.07.09 |
---|---|
백준 11066번: 파일 합치기 (0) | 2020.07.08 |
백준 1965번: 상자넣기 (0) | 2020.07.06 |
백준 6359번: 만취한 상범 (0) | 2020.07.06 |
백준 1937번: 욕심쟁이 판다 (0) | 2020.07.06 |