백준 1799 비숍
백준 1799 비숍
2022년 12월 17일
2022년 12월 17일
cpp, 완전 탐색
문제
문제
풀이
풀이
비숍의 이동 범위는 다음과 같다.
보드판을 다음과 같이 두 영역으로 나누면, 서로 다른 영역에 있는 비숍끼리는 만나지 않는다.
n-queen 문제에서의 풀이와 마찬가지로 특정 위치의 말을 선택할 경우, 해당 위치의 말이 이동 가능한 영역을 제외해 나가면서 선택하면 된다.
비숍이 이동 가능한 영역인 우상향 영역 ( n - 1 + ( x - y ) ) 과 우하향 영역 ( x + y ) 을 표시해 나가면서 최대로 선택 가능한 비숍의 갯수를 구한다.
코드
코드
#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