BOJ 1799 비숍


사용한 알고리즘

  • 완전탐색, DFS

알고리즘 설명

  • 체스판에 대각선의 종류는 두종류 이다.
  • Case1. 오른쪽 아래 방향의 대각선
  • Case2. 오른쪽 윗 방향의 대각선
  • 이 두 종류의 대각선으로 보드의 모든 좌표에서 만드는 대각선을 표현할 수 있다.
  • 좌표를 (x,y)라고 하면 아래를 모두 만족한다.
  • Case1. (x+y)가 같은 값이면 하나의 오른쪽 아래 방향의 대각선에 모두 포함 된다.
  • Case2. (N-1-x+y)가 같은 값이면 하나의 오른쪽 윗 방향의 대각선에 모두 포함 된다.
  • 이를 이용하여 놓을 수 있는 좌표에 하나씩 놓아보며 모두 확인하면 된다.
  • 이러한 확인을 DFS를 이용하여 완전 탐색을 진행한다.
  • 이 확인 작업은 N이 10이므로 2^(10*10)으로 무작정하면 시간초과를 피할 수 없다.
  • 이 때문에 비숍은 체스판의 흰색과 검정색 판을 보았을때 같은 색인 부분만 영향을 미칠 수 있다.
  • 이 점을 이용하여 흰색 판에만 비숍을 놓아보고, 검정색 판에만 놓아 보면된다.
  • 이를 이용하면 2^(5*5)로 획기적으로 시간을 단축시켜 TLE를 모면할 수 있다.

풀이

// baekjoon 1799 yechan
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAX_N=11;

int N, board[MAX_N][MAX_N], ans;
// diag[0]: 오른쪽 아래 방향의 대각선들
// diag[1]: 오른쪽 윗 방향의 대각선들
int diag[2][MAX_N*2];

// 이미 비숍이 놓아져 있어 놀수 없는 경우를 판단
inline bool check(int x, int y) {
	return !diag[0][x+y] && !diag[1][N-1-x+y];
}

// 대각선 좌표 체크
inline void mark(int x, int y, int value) {
	diag[0][x+y]=diag[1][N-1-x+y]=value;
}

int dfs(int x, int y) {
	if (x == N) return 0;
	int ret = 0;
// x,y 좌표에 놓을수 있는 경우
// 체스판을 보았을때 같은 색깔인 부분만 확인
// 현재 (x,y)좌표에 비숍을 놓고 (x, y+2)좌표 확인하러 가기
// 또는 현재 (x, y)좌표에 비숍을 놓고 (x+1, (y+1)%2) 좌표 확인하러 가기
// 확인 후 다시 x,y 좌표를 지워줌
	if (board[x][y] && check(x, y)) {
		mark(x, y, 1);
		if (y+2 < N) ret = max(ret, dfs(x, y+2) + 1);
		else ret = max(ret, dfs(x+1, (y+1)%2) + 1);
		mark(x, y, 0);
	}

// 현재 (x,y)에 비숍을 놓지 않고 다음을 확인함
// 현재 (x,y)좌표에 비숍을 놓지 않고 (x, y+2)좌표 확인하러 가기
// 또는 현재 (x, y)좌표에 비숍을 놓지 않고 (x+1, (y+1)%2) 좌표 확인하러 가기
	if (y+2 < N) ret = max(ret, dfs(x, y+2));
	else ret = max(ret, dfs(x+1, (y+1)%2));

	return ret;
}

int main() {
	scanf("%d", &N);
	for (int i=0; i<N; i++)
		for (int j=0; j<N; j++)
			scanf("%d", &board[i][j]);

	ans = dfs(0, 0);
	ans += dfs(0, 1);

	printf("%d\n", ans);
	return 0;
}



© 2020.08. by fbdp1202

Powered by theorydb