可以把一行分成多行,一列分出多列,然后用行和列坐标之间建二分图,求最大匹配.
#include <iostream>
#include <cstdio>
#include <memory.h>
using namespace std;
const int maxn = 40;
char grid[5][5];
bool g[maxn][maxn], vis[maxn];
int rg[5][5], cg[5][5], fa[maxn], n, m;
bool dfs(int u){
for (int v = 1; v <= m; ++v){
if(g[u][v] && !vis[v]){
vis[v] = 1;
if(fa[v] == 0 || dfs(fa[v])){
fa[v] = u;
return true;
}
}
}
return false;
}
int hungary(){
int ans = 0;
memset(fa, 0, sizeof(fa));
for (int i = 1; i <= n; ++i){
memset(vis, 0, sizeof(vis));
if(dfs(i))ans++;
}
return ans;
}
int main(){
while (scanf("%d\n", &n) && n){
memset(g, 0, sizeof(g));
memset(rg, 0, sizeof(rg));
memset(cg, 0, sizeof(cg));
for (int i = 0; i < n; ++i){
gets(grid[i]);
}
int r = 1;
for (int i = 0; i < n; ++i){
for (int j = 0; j < n; ++j){
if(grid[i][j] == 'X'){
r++;
}else{
rg[i][j] = r;
}
}
++r;
}
int c = r + 1;
for (int i = 0; i < n; ++i){
for (int j = 0; j < n; ++j){
if(grid[j][i] == 'X'){
c++;
}else{
cg[j][i] = c;
}
}
++c;
}
for (int i = 0; i < n; ++i){
for (int j = 0; j < n; ++j){
if(grid[i][j] == '.'){
g[rg[i][j]][cg[i][j]] = g[cg[i][j]][rg[i][j]] = 1;
}
}
}
n = r, m = c;
printf("%d\n",hungary());
}
return 0;
}
搜索的做法:
#include <iostream>
#include <cstdio>
#include <memory.h>
using namespace std;
const int maxn = 5;
char grid[maxn][maxn];
bool vis[maxn][maxn];
int di[] = {-1, 1, 0, 0}, dj[] = {0, 0, -1, 1}, n, ans;
bool canput(int ci, int cj){
for (int i = 0; i < 4; ++i){
for (int ti = ci, tj =cj; ti >= 0 && ti < n && tj >= 0 && tj < n && grid[ti][tj] == '.'; ti += di[i], tj += dj[i]){
if(vis[ti][tj])return false;
}
}
return true;
}
void dfs(int cp, int cnt){
if(cnt > ans){
ans = cnt;
}
if(cp >= n * n)return;
int ci = cp / n, cj = cp %n;
if(grid[ci][cj] == '.' && canput(ci, cj)){
vis[ci][cj] = 1;
dfs(cp + 1, cnt + 1);
vis[ci][cj] = 0;
}
dfs(cp + 1, cnt);
}
int main(){
while (scanf("%d\n", &n) && n){
for (int i = 0; i < n; ++i){
gets(grid[i]);
}
ans = 0;
memset(vis, 0, sizeof(vis));
dfs(0, 0);
printf("%d\n", ans);
}
return 0;
}