My Profile

김형훈

안녕하세요.
김형훈입니다.

백준 1799 비숍

백준 1799 비숍

2022년 12월 17일

2022년 12월 17일

cpp, 완전 탐색

문제

문제

풀이

풀이

비숍의 이동 범위는 다음과 같다.

image-20221128180758314

보드판을 다음과 같이 두 영역으로 나누면, 서로 다른 영역에 있는 비숍끼리는 만나지 않는다.

image-20221128180758314

n-queen 문제에서의 풀이와 마찬가지로 특정 위치의 말을 선택할 경우, 해당 위치의 말이 이동 가능한 영역을 제외해 나가면서 선택하면 된다.
비숍이 이동 가능한 영역인 우상향 영역 ( n - 1 + ( x - y ) ) 과 우하향 영역 ( x + y ) 을 표시해 나가면서 최대로 선택 가능한 비숍의 갯수를 구한다.

image-20221128180758314

코드

코드

#include <bits/stdc++.h>
using namespace std;

int n,ans[2];
bool lower[22][2];
vector<pair<int,int>> upper[22][2];


void collect_0(int cur, int cnt){
    if(cur==2*n){
        // 최대 탐색 횟수에 도달하면 답 갱신
		if(cnt > ans[0]) ans[0] = cnt;
		return;
	}
    // 흑색 영역의 각각의 우상향 영역에 대해 가능한 위치 선택.
	for(auto e:upper[cur][0]){
		auto [x,y] = e;
        if(lower[n-1+(x-y)][0]) continue;
		// 선택한 위치의 우하향 영역 표시
        lower[n-1+(x-y)][0] = true;
		collect_0(cur+1,cnt+1);
		lower[n-1+(x-y)][0] = false;
	}
    // 흑색의 우상향 영역에 포함되지 않는 부분(cur = 1, 3, 5, ...)과
    // 비숍을 둘 수 없는 영역은 제외한다.(cnt를 증가하지 않는다.)
	collect_0(cur+1,cnt);
}
void collect_1(int cur, int cnt){
	if(cur==2*n){
		if(cnt > ans[1]) ans[1] = cnt;
		return;
	}
	for(auto e:upper[cur][1]){
		auto [x,y] = e;
		if(lower[n-1+(x-y)][1]) continue;
		lower[n-1+(x-y)][1] = true;
		collect_1(cur+1,cnt+1);
		lower[n-1+(x-y)][1] = false;
	}
	collect_1(cur+1,cnt);
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> n;
	for(int i=0; i<n; ++i)
		for(int j=0; j<n; ++j){
			int val; cin >> val;
            // 두 영역에 대해 비숍을 놓을 수 있는 위치 정보를 우 상향 기준으로 기록한다.
            // 이때 두 영역을 나누는 기준은 홀,짝((i*n+j)%2)이 아니다.
			if(val) upper[i+j][(i+j+1)&1].push_back({i,j});
		}
	collect_0(0,0);
	collect_1(0,0);
	cout << ans[0] + ans[1];
}

결과

결과

Copyright © 2024 Hyunghoon Kim