2 분 소요

테트로미노 (백준 Gold 4)

https://www.acmicpc.net/problem/14500

Image

정사각형 4개를 모여 붙인 도형을 테트로미노라 한다
임의의 ‘맵’에서 다음과 같이 5가지 도형을
배치하여 도형이 ‘덮은 수들의 합’이 가장 큰 것을 구하는 문제

  • 각 도형은 적절히 ‘회전/대칭’ 시킬 수 있음

풀이 방법

단순히 브루트 포스 문제인 것처럼 보이나
조금 더 자세히 생각해보면

저 4가지 모형을 하나의 점에 두고
각각의 모형들을 회전 ‘대칭’ 시켜보면
사실상 시작점에서 ‘뻣어나가는’ 길이 4개 짜리 dfs라고 봐도 좋다
(단, ‘ㅜ’ 모양 제외)

  • ‘ㅜ’ 모양이 아닌 것들은 백트래킹을 통해 구할 수 있다

  • ‘ㅜ’ 모양의 경우는 1번 전진하였을때
    다른 방향 2개를 잡아 검사하는 쪽으로 예외처리를 해주면 된다

제출 코드

#include<iostream>
#include<vector>

using namespace std;

const int dirY[4] = { -1,0,1,0 };
const int dirX[4] = { 0, 1,0,-1 };

int n, m;

int best(vector<vector<int>>& map, vector<vector<bool>>& visit, int startY, int startX, int count,int nowSum)
{
	if (startY < 0 || startY >= n ||
		startX < 0 || startX >= m)
		return 0;

	if (visit[startY][startX])
		return 0;

	if (count == 3)
	{
		return nowSum + map[startY][startX];
	}

	int ret = 0;
	visit[startY][startX] = true;
	
	for (int i = 0; i < 4; i++)
	{
		int ny = startY + dirY[i];
		int nx = startX + dirX[i];

		ret = max(ret, best(map, visit, ny, nx, count + 1, nowSum + map[startY][startX]));
	}

	// ㅜ 모양에 대한 예외처리
	if (count == 1)
	{
		for (int i = 0; i < 4; i++)
		{
			int ny = startY + dirY[i];
			int nx = startX + dirX[i];
			int j = i + 1;

			if (j > 3)
				j = 0;
			int nny = startY + dirY[j];
			int nnx = startX + dirX[j];

			if (ny < 0 || ny >= n ||
				nx < 0 || nx >= m ||
				nny < 0 || nny >= n ||
				nnx < 0 || nnx >= m ||
				visit[ny][nx] ||
				visit[nny][nnx])
				continue;

			ret = max(ret, nowSum + map[startY][startX] + map[ny][nx] + map[nny][nnx]);
		}
	}

	visit[startY][startX] = false;

	return ret;
}

int main()
{
	cin >> n >> m;
	vector<vector<int>> map(n,vector<int>(m,-1));
	vector<vector<bool>> visit(n,vector<bool>(m,false));

	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			cin >> map[i][j];
	
	int bestV = 0;
	
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			bestV = max(bestV, best(map,visit, i, j, 0, 0));

	cout << bestV;
	return 0;
}

결과

Image

주어지는 예제의 범위가 약 500개 내외인 경우
보통은 백트래킹이나 브루트 포스를 감안하여 접근해보는 방식도 존재한다
(1000개 이상인 경우, 해당 알고리즘 적용 시 시간초과가 발생할 것이 뻔하므로!)

그렇기에 보통 브루트 포스 문제가
‘판단력’과 ‘구현력’을 요구하는 경우가 많은 듯하다

댓글남기기