Study hard

(c++)백준 14500번: 테트로미노 본문

백준/브루트 포스

(c++)백준 14500번: 테트로미노

Nimgnoej 2020. 8. 25. 14:17

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

 

14500번: 테트로미노

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다. 정사각형은 서로 겹치면 안 된다. 도형은 모두 연결되어 있어야 한다. 정사각형의 변�

www.acmicpc.net

[풀이]

브루트 포스 문제이므로 만들 수 있는 모든 테트로미노에 대해 그 합이 가장 최대인 수를 구하면 된다.

위와 같은 모양은 2차원 map에서 상하좌우 경로를 탐색하는 방법으로 쉽게 구할 수 있지만,

위와 같은 모양은 3칸까지 선택한 상황에서, 현재 칸의 상하좌우 칸을 검사했을 때 그 칸이 이미 선택된 경우 그 칸에 대해 상하좌우 칸을 다시 검색하여 만들 수 있다.

이렇게 4칸을 모두 선택했으면 선택된 칸들에 쓰인 수들의 합을 구해 최댓값을 갱신해나가면 된다.

 

#include <iostream>
#include <vector>
#include <algorithm>//max
using namespace std;

int N, M;
const int dx[] = { -1,1,0,0 };//좌, 우
const int dy[] = { 0,0,-1,1 };//상, 하
int Map[500][500];
bool check[500][500];
vector<pair<int, int>>v;
int Max = -1;

int getSum() {
	int sum = 0;
	for (int i = 0; i < 4; i++) {
		int x = v[i].first;
		int y = v[i].second;
		sum += Map[x][y];
	}
	return sum;
}

//모든 경우의 테트로미노 확인
void getPos(int curx, int cury, int cnt) {
	if (cnt == 4) {
		int res = getSum();
		Max = max(Max, res);
		return;
	}

	for (int i = 0; i < 4; i++) {
		int nx = curx + dx[i];
		int ny = cury + dy[i];
		if (nx < 0 || nx >= N || ny < 0 || ny >= M)
			continue;
		if (check[nx][ny] == false) {
			check[nx][ny] = true;
			v.push_back(make_pair(nx, ny));
			getPos(nx, ny, cnt + 1);
			v.pop_back();
			check[nx][ny] = false;
		}
		//ㅗ모양일 때(다음 좌표가 이미 선택된 경우 그 좌표에서 다른 좌표 탐색하면 ㅗ모양 만들 수 있음)
		else if (cnt==3) {
			//nx, ny에 대해 상하좌우 확인
			for (int j = 0; j < 4; j++) {
				int nnx = nx + dx[j];
				int nny = ny + dy[j];
				if (nnx < 0 || nnx >= N || nny < 0 || nny >= M)
					continue;
				if (check[nnx][nny] == false) {
					check[nnx][nny] = true;
					v.push_back(make_pair(nnx, nny));
					getPos(nnx, nny, cnt + 1);
					v.pop_back();
					check[nnx][nny] = false;
				}
			}
		}
	}
}

void solution() {
	cin >> N >> M;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			cin >> Map[i][j];
		}
	}
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) {
			check[i][j] = true;
			v.push_back(make_pair(i, j));
			getPos(i, j, 1);
			v.pop_back();
			check[i][j] = false;
		}
	}

	cout << Max << '\n';
}

int main() {
	solution();
	return 0;
}