[백준] 1760 N-Rook
문제
N-Queen 문제를 풀어본 일이 있을 것이다. 격자판에 N개의 Queen을 배치하되, 각 Queen이 서로를 공격할 수 없게 배치하려면 N은 최대 얼마까지 가능한지를 알아내는 문제이다.
이번에는 Rook을 가지고 같은 문제를 풀어 보자. Rook은 격자판의 같은 열, 혹은 같은 행에 다른 말이 있을 경우, 그 말을 공격할 수 있는 말이다.
다만, 이 경우에 문제가 그 가치를 확보하기 위해서는, 격자판을 약간 변형해야 한다. 격자판에 벽과 구덩이를 도입하자.
벽을 사이에 두고 있는 두 Rook은, 서로 볼 수 없으므로, 서로 공격할 수가 없다. 물론 벽이 놓여 있는 격자에는 Rook을 놓을 수 없다.
반면, 구덩이를 사이에 두고 있는 두 Rook은 서로 공격을 시도한다. (아마 공격 도중에 구덩이에 빠지겠지만.) 따라서 두 Rook이 구덩이를 사이에 두고 마주보도록 배치해서는 안 된다. 또, 구덩이를 파 놓은 격자에도 Rook을 놓을 수 없다.
격자판의 모양이 주어졌을 때, Rook을 가장 많이 배치하기 위한 방법을 알아내는 프로그램을 작성하시오.
입력
첫째 줄에 격자의 크기를 나타내는 두 자연수 N, M이 주어진다. 격자가 N행 M열로 이루어져 있다는 의미이다. (1 ≤ N, M ≤ 100) 둘째 줄부터는 격자의 모양을 나타내는 정보가 한 줄에 한 행씩 주어진다. 0은 빈 격자, 1은 구덩이가 파인 격자, 2는 벽이 놓인 격자를 의미한다.
출력
첫째 줄에 배치할 수 있는 Rook의 최대 개수를 출력한다.
구덩이에는 룩을 배치할 수 없지만, 같은행에서는 서로 공격을 할 수있습니다.
벽에는 룩을 배치할 수도 업고, 공격할수도없습니다.
이분매칭으로 해결합니다.
#include<bits/stdc++.h>
#define FAST ios_base::sync_with_stdio(false);cin.tie(NULL)
#define mset(v) memset(v,0,sizeof(v));
#define rep(i,a) for(int i=0;i<a;++i)
#define REP(i,a) for(int i=1;i<=a;++i)
using namespace std;
typedef long long ll;
typedef pair<int, int> pi;
typedef tuple<int, int, int>ti;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
int dy[] = { -1,0,1,0 }, dx[] = { 0,1,0,-1 };
int mp[101][101], m[101][101], v[10001], d[10001];
int N, M, R, C, ans;
vi adj[10001];
bool dfs(int k) {
for (auto r : adj[k]) {
if (v[r])continue;
v[r] = 1;
if (!d[r] || dfs(d[r])) {
d[r] = k;
return 1;
}
}
return 0;
}
int main() {
FAST;
cin >> N >> M;
rep(i, N)rep(j, M)cin >> mp[i][j];
rep(i, N) {
bool f = 0;
rep(j, M) {
if (mp[i][j] == 2)
f = 0;
else {
if (!f)R++;
m[i][j] = R;
f = 1;
}
}
}
rep(i, M) {
bool f = 0;
rep(j, N) {
if (mp[j][i] == 2)
f = 0;
else if(mp[j][i]==0) {
if (!f)C++;
adj[m[j][i]].push_back(C);
f = 1;
}
}
}
REP(i, R) {
mset(v);
if (dfs(i))ans++;
}
cout << ans;
}