※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 1574번 문제인 룩 어택이다.
문제는 아래 링크를 확인하자.

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

 

1574번: 룩 어택

첫째 줄에 체스판의 크기 R과 C가 주어지고, 빈 칸의 개수 N이 주어진다. 둘째 줄부터 N개의 줄에 빈 칸의 좌표가 주어진다. 좌표는 (행, 열)의 형태로 주어지고, 가장 윗 행은 1번 행이고, 가장 왼

www.acmicpc.net

"빈 칸"에 룩을 놓을 수 없음에 주의하자.

한 열에 룩을 하나씩만 놓을 수 있으므로, 각 행마다 겹치지 않게 열을 하나씩 최대한 고르면서 가능한 한 많은 열을 고르는 것으로 문제를 생각할 수 있다. 이 상황은 각 행과 열을 노드로 하는 이분그래프(bipartite graph)로 모델링을 할 수 있다. 이 그래프에서 maximum bipartite matching 알고리즘을 이용하면 문제를 해결할 수 있다.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;

bool board[301][301];

vector<int> G[301];
int visited[301];
int matching[301];

int bipartite(int current) {
	if (visited[current]) return 0;
	visited[current] = 1;
	for (auto node : G[current]) {
		if (matching[node] == 0) {
			matching[node] = current;
			return 1;
		}
		if (bipartite(matching[node])) {
			matching[node] = current;
			return 1;
		}
	}
	return 0;
}

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

	int R, C, N; cin >> R >> C >> N;
	while (N--) {
		int x, y; cin >> x >> y;
		board[x][y] = 1;
	}

	for (int r = 1; r <= R; r++) {
		for (int c = 1; c <= C; c++) {
			if (board[r][c]) continue;
			G[r].push_back(c);
		}
	}

	int ans = 0;
	for (int i = 1; i <= R; i++) {
		memset(visited, 0, sizeof(visited));
		ans += bipartite(i);
	}

	cout << ans;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 2570 // C++] 비숍2  (0) 2021.07.18
[BOJ 5398 // C++] 틀렸습니다  (0) 2021.07.17
[BOJ 13344 // C++] Chess Tournament  (0) 2021.07.15
[BOJ 15701 // C++] 순서쌍  (0) 2021.07.14
[BOJ 20294 // C++] 에어컨 설치  (0) 2021.07.13

+ Recent posts