문제 링크


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

 

14500번: 테트로미노

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

www.acmicpc.net

접근 방법


 시작지점부터 상하좌우로 인접한 지점을 따라가며 백트래킹을 하여 테트로미노를 이루는 4칸이 완성이 되었을 때 최댓값을 갱신해주며 풀면 된다. 하지만 주의해야될 점이있다. 

 

 

 이런 경우에 3과 4는 인접해 있지 않지만 위와 같은 경우도 문제에서 요구하는 경우의 수가 되기 때문이다.

이 점을 유의하여 문제를 풀어보자.

if (cnt == 3) {
	if (stk[0].x == stk[1].x && stk[1].x == stk[2].x) {
		info fuck[2] = { {1, 0} ,{-1, 0} };
		for (int i = 0; i < 2; i++) {
			int next_x = stk[1].x + fuck[i].x;
			int next_y = stk[1].y + fuck[i].y;
			if (0 <= next_x && next_x < N && 0 <= next_y && next_y < M && !visited[next_x][next_y]) {
				visited[next_x][next_y] = true;
				stk.push_back({ next_x, next_y });
				solve(cnt + 1, next_x, next_y);
				stk.pop_back();
				visited[next_x][next_y] = false;
			}
		}
	}
}

 일단 그림에서 설명한 것과 동일하게 3개의 폴리오미노가 수평으로 나란할 때, 즉 코드상으로 x의 값이 동일 할때에 대한 처리 부분이다. 수직으로 나란한 경우도 크게 다른점이 없으니 수평인 경우만 설명하겠다.

 

 일단 3개의 폴리오미노가 이루어졌을 때 -> if(cnt == 3) ) 지금까지 이룬 폴리오미노의

집합 stk[i] (0 <= i < 3) 의 x값이 모두 동일 하다면 -> if (stk[0].x == stk[1].x && stk[1].x == stk[2].x)

3개의 폴리오미노중 가운대인 stk[1]에 위 아래 방향으로 더하여(int next_x = stk[1].x + fuck[i].x,  
int next_y = stk[1].y + fuck[i].y) 다음 스탭으로 진행을 시키면 된다. 

  

소스 코드


#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

typedef struct info {
	int x;
	int y;
};

vector <info> stk;
info next_dir[4] = { {1,0}, {-1,0}, {0,-1}, {0,1} };
int map[500][500];
bool visited[500][500];
int N, M;
int result = -1;

void solve(int cnt, int x, int y) {
	if (cnt == 4) {
		int sum = 0;
		for (int i = 0; i < 4; i++) {
			sum += map[stk[i].x][stk[i].y];
			result = max(result, sum);
		}
		return;
	}
	if (cnt == 3) {
		if (stk[0].x == stk[1].x && stk[1].x == stk[2].x) {
			info fuck[2] = { {1, 0} ,{-1, 0} };
			for (int i = 0; i < 2; i++) {
				int next_x = stk[1].x + fuck[i].x;
				int next_y = stk[1].y + fuck[i].y;
				if (0 <= next_x && next_x < N && 0 <= next_y && next_y < M && !visited[next_x][next_y]) {
					visited[next_x][next_y] = true;
					stk.push_back({ next_x, next_y });
					solve(cnt + 1, next_x, next_y);
					stk.pop_back();
					visited[next_x][next_y] = false;
				}
			}
		}
		else if (stk[0].y == stk[1].y && stk[1].y == stk[2].y){
			info fuck[2] = { {0, 1} ,{0, -1} };
			for (int i = 0; i < 2; i++) {
				int next_x = stk[1].x + fuck[i].x;
				int next_y = stk[1].y + fuck[i].y;
				if (0 <= next_x && next_x < N && 0 <= next_y && next_y < M && !visited[next_x][next_y]) {
					visited[next_x][next_y] = true;
					stk.push_back({ next_x, next_y });
					solve(cnt + 1, next_x, next_y);
					stk.pop_back();
					visited[next_x][next_y] = false;
				}
			}
		}
	}
	for (int i = 0; i < 4; i++) {
		int next_x = x + next_dir[i].x;
		int next_y = y + next_dir[i].y;
		if (0 <= next_x && next_x < N && 0 <= next_y && next_y < M && !visited[next_x][next_y]) {
			visited[next_x][next_y] = true;
			stk.push_back({ next_x, next_y });
			solve(cnt + 1, next_x, next_y);
			stk.pop_back();
			visited[next_x][next_y] = false;
		}
	}

}

int main() {

	ios_base::sync_with_stdio(NULL);
	cin.tie(0);
	cout.tie(0);
	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++) {
			visited[i][j] = true;
			stk.push_back({ i,j });
			solve(1, i, j);
			stk.pop_back();
			visited[i][j] = false;
		}
	}
	cout << result << "\n";
}

개발 환경 : VS 2019

질문, 지적 환영입니다.

'알고리즘 > 백준' 카테고리의 다른 글

[C++} 백준 14890 경사로  (0) 2020.05.25
[C++] 백준 15683 감시  (0) 2020.05.20
[C++] 백준 2206 벽 부수고 이동하기  (0) 2020.05.19
[C++] 백준 1697 숨바꼭질  (0) 2020.05.19
[C++] 백준 14501 퇴사  (0) 2020.05.19

+ Recent posts