문제 링크입니다: https://www.acmicpc.net/problem/1799
1799번: 비숍
첫째 줄에 체스판의 크기가 주어진다. 체스판의 크기는 10이하의 자연수이다. 둘째 줄부터 아래의 예와 같이 체스판의 각 칸에 비숍을 놓을 수 있는지 없는지에 대한 정보가 체스판 한 줄 단위로 한 줄씩 주어진다. 비숍을 놓을 수 있는 곳에는 1, 비숍을 놓을 수 없는 곳에는 0이 빈칸을 사이에 두고 주어진다.
www.acmicpc.net
먼저 이 문제는 Crocus님의 코드를 참고하여 풀었습니다.
(https://www.crocus.co.kr/775)
체스 문제가 나오면 이분그래프를 통해 접근해야한다는 것을 Crocus님 통해 알 수 있었습니다.
비숍은 대각선으로 움직이기 때문에 좌상단부터 우하단, 좌하단부터 우상단까지 대각선을 통해 연결할 수 있는 타일에 각각 번호를 부여한 뒤 비숍이 위치할 수 있는 칸에 대해 이분 그래프를 형성하면 되는 문제였습니다.
더 자세한 내용은 Crocus님 블로그를 참고하시길 바랍니다.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <cstdio> | |
#include <vector> | |
#include <algorithm> | |
using namespace std; | |
const int MAX_N = 52; | |
const int MAX_V = 102; | |
vector<int> adj[MAX_V]; | |
vector<int> aMatch; | |
vector<int> bMatch; | |
int map[MAX_N][MAX_N]; | |
int visited[MAX_V]; | |
int visitedCnt; | |
int Left[MAX_N][MAX_N]; | |
int Right[MAX_N][MAX_N]; | |
int N; | |
int leftMax, rightMax; | |
void fillLeft() | |
{ | |
int y = 1; | |
int x = N; | |
int cnt = 1; | |
// 오른쪽 위 시작 기준 대각선은 총 N번 반복 | |
for (int k = 0; k < 2 * N - 1; k++) | |
{ | |
int tempY = y; | |
int tempX = x; | |
while (tempY <= N) | |
{ | |
Left[tempY++][tempX++] = cnt; | |
} | |
cnt++; | |
x--; | |
} | |
} | |
void fillRight() | |
{ | |
int y = N; | |
int x = N; | |
int cnt = 1; | |
// 오른쪽 아래 시작 기준 대각선은 총 N번 반복 | |
for (int k = 0; k < 2 * N - 1; k++) | |
{ | |
int tempY = y; | |
int tempX = x; | |
while (tempY > 0) | |
{ | |
Right[tempY--][tempX++] = cnt; | |
} | |
cnt++; | |
x--; | |
} | |
} | |
bool DFS(int a) | |
{ | |
if (visited[a] == visitedCnt) | |
{ | |
return false; | |
} | |
visited[a] = visitedCnt; | |
for (int next = 0; next < adj[a].size(); next++) | |
{ | |
int b = adj[a][next]; | |
if (bMatch[b] == -1 || DFS(bMatch[b])) | |
{ | |
aMatch[a] = b; | |
bMatch[b] = a; | |
return true; | |
} | |
} | |
return false; | |
} | |
int bipartiteMatch() | |
{ | |
aMatch = vector<int>(leftMax + 1, -1); | |
bMatch = vector<int>(rightMax + 1, -1); | |
int result = 0; | |
for (int i = 1; i <= leftMax; i++) | |
{ | |
visitedCnt++; | |
result += DFS(i); | |
} | |
return result; | |
} | |
int main() | |
{ | |
ios_base::sync_with_stdio(0); | |
cin >> N; | |
for (int i = 1; i <= N; i++) | |
{ | |
for (int j = 1; j <= N; j++) | |
{ | |
cin >> map[i][j]; | |
} | |
} | |
fillLeft(); | |
fillRight(); | |
// 1일때만 간선 연결(0일때는 벽이니) | |
int maxL = 0, maxR = 0; | |
for (int i = 1; i <= N; i++) | |
{ | |
for (int j = 1; j <= N; j++) | |
{ | |
if (map[i][j] == 1) | |
{ | |
adj[Left[i][j]].push_back(Right[i][j]); | |
maxL = max(maxL, Left[i][j]); | |
maxR = max(maxR, Right[i][j]); | |
} | |
} | |
} | |
// 이분매칭에 이용 될 n과 m은 maxL, maxR로 교체된다. | |
leftMax = maxL; | |
rightMax = maxR; | |
cout << bipartiteMatch() << "\n"; | |
return 0; | |
} |


개발환경:Visual Studio 2017
지적, 조언, 질문 환영입니다! 댓글 남겨주세요~
반응형
'알고리즘 > BOJ' 카테고리의 다른 글
백준 17826번 나의 학점은? (0) | 2019.11.04 |
---|---|
백준 17836번 공주님을 구해라! (2) | 2019.11.04 |
백준 15666번 N과 M (12) (0) | 2019.10.22 |
백준 15665번 N과 M (11) (0) | 2019.10.22 |
백준 15664번 N과 M (10) (0) | 2019.10.22 |