알고리즘/BAEKJOON
[백준] 14500번 테트로미노 - C++
거북이 코딩
2024. 11. 9. 17:51
테트로미노
N x M 크기의 보드에 정사각형 4개로 이루어진 블록을 무작위로 배치했을 때 블록에 가려진 정수의 합이 가장 큰 경우의 값을 찾는 문제입니다. 어떻게 풀어야 하나.. 고민하다가 아이디어가 당장 안 떠올라서 노가다 - 멋있는 말로 브루트 포스 - 로 풀었습니다.
풀이방법
그림과 같이 엑셀에 모든 블록의 경우의 수를 정리해 보니까 19가지의 블록을 최대 500 x 500의 보드에 배치하는 것이기 때문에 시간제한 2초 안에 성공할 수 있을 것 같아서 브루트포스를 선택했습니다. 그림과 같이 블록들을 가로 x 세로의 크기대로 분류하면 총 5가지의 유형으로 분류할 수 있습니다. 유형별로 2중 for문을 돌리고 for문 안에서 공통된 블록은 한 번만 계산함으로써 최대한 연산을 줄였습니다.
코드
#include <iostream>
#include <vector>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<vector<int>> paper(n, vector<int>(m));
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
cin >> paper[i][j];
int max = 0;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m - 3; ++j)
{
int sum = paper[i][j] + paper[i][j + 1] + paper[i][j + 2] + paper[i][j + 3];
if (sum > max)
max = sum;
}
}
for (int i = 0; i < n - 3; ++i)
{
for (int j = 0; j < m; ++j)
{
int sum = paper[i][j] + paper[i + 1][j] + paper[i + 2][j] + paper[i + 3][j];
if (sum > max)
max = sum;
}
}
for (int i = 0; i < n - 1; ++i)
{
for (int j = 0; j < m - 1; ++j)
{
int sum = paper[i][j] + paper[i][j + 1] + paper[i + 1][j] + paper[i + 1][j + 1];
if (sum > max)
max = sum;
}
}
for (int i = 0; i < n - 2; ++i)
{
for (int j = 0; j < m - 1; ++j)
{
int left_bar = paper[i][j] + paper[i + 1][j] + paper[i + 2][j];
int sum = left_bar + paper[i][j + 1];
if (sum > max)
max = sum;
sum = left_bar + paper[i + 1][j + 1];
if (sum > max)
max = sum;
sum = left_bar + paper[i + 2][j + 1];
if (sum > max)
max = sum;
int right_bar = paper[i][j + 1] + paper[i + 1][j + 1] + paper[i + 2][j + 1];
sum = right_bar + paper[i][j];
if (sum > max)
max = sum;
sum = right_bar + paper[i + 1][j];
if (sum > max)
max = sum;
sum = right_bar + paper[i + 2][j];
if (sum > max)
max = sum;
int middle_bar = paper[i + 1][j] + paper[i + 1][j + 1];
sum = middle_bar + paper[i][j] + paper[i + 2][j + 1];
if (sum > max)
max = sum;
sum = middle_bar + paper[i][j + 1] + paper[i + 2][j];
if (sum > max)
max = sum;
}
}
for (int i = 0; i < n - 1; ++i)
{
for (int j = 0; j < m - 2; ++j)
{
int upper_bar = paper[i][j] + paper[i][j + 1] + paper[i][j + 2];
int sum = upper_bar + paper[i + 1][j];
if (sum > max)
max = sum;
sum = upper_bar + paper[i + 1][j + 1];
if (sum > max)
max = sum;
sum = upper_bar + paper[i + 1][j + 2];
if (sum > max)
max = sum;
int lowwer_bar = paper[i + 1][j] + paper[i + 1][j + 1] + paper[i + 1][j + 2];
sum = lowwer_bar + paper[i][j];
if (sum > max)
max = sum;
sum = lowwer_bar + paper[i][j + 1];
if (sum > max)
max = sum;
sum = lowwer_bar + paper[i][j + 2];
if (sum > max)
max = sum;
int middle_bar = paper[i][j + 1] + paper[i + 1][j + 1];
sum = middle_bar + paper[i][j] + paper[i + 1][j + 2];
if (sum > max)
max = sum;
sum = middle_bar + paper[i][j + 2] + paper[i + 1][j];
if (sum > max)
max = sum;
}
}
cout << max;
return 0;
}
마치며
다풀고 다른 사람의 풀이도 보고 복기해 보니 dfs로도 풀 수 있지만 의외로 브루트포스가 메모리도 덜 쓰고 성능도 좋았습니다. 하지만 dfs로 풀면 멋있기 때문에 멋쟁이 분들은 dfs로 도전해 보셔도 좋을 것 같습니다.