HDU-1045 Fire Net
先行列分块,然后对于被强隔开的行列就分成几块,这样每个格依旧对应着行方向上的一块和列方向上的一块。
最后行列二分匹配。
#include <cstdlib> #include <cstdio> #include <cstring> //#include <cmath> #include <algorithm> #include <fstream> #include <iostream> #define rep(i, l, r) for(int i=l; i<=r; i++) #define down(i, l, r) for(int i=l; i>=r; i--) #define N 10 using namespace std; int read() { int x=0, f=1; char ch=getchar(); while (ch<'0' || ch>'9') { if (ch=='-') f=-1; ch=getchar(); } while (ch>='0' && ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } struct edge{int y, n;} e[N*N*2]; int fir[N], en; int n, xn, yn, mx[N][N], my[N][N], k[N], ans; char s[N]; bool map[N][N], b[N]; void Add(int x, int y) { en++, e[en].y=y, e[en].n=fir[x], fir[x]=en; } bool Find(int x) { int o=fir[x], y=e[o].y; while (o) { if (!b[y]) { b[y]=1; if (!k[y] || Find(k[y])) { k[y]=x; return true; } } o=e[o].n, y=e[o].y; } return false; } int main() { n=read(); while (n) { rep(i, 1, xn) fir[i]=0; xn=yn=ans=en=0; rep(i, 1, n) { scanf("%s", s); rep(j, 1, n) map[i][j] = s[j-1]=='X' ? 1 : 0; } rep(i, 1, n) { int a=0; rep(j, 1, n) if (!map[i][j]) { if (!a) a=++xn; mx[i][j]=a; } else a=0; } rep(j, 1, n) { int a=0; rep(i, 1, n) if (!map[i][j]) { if (!a) a=++yn; my[i][j]=a; } else a=0; } rep(i, 1, n) rep(j, 1, n) if (!map[i][j]) Add(mx[i][j], my[i][j]); rep(i, 1, yn) k[i]=0; rep(i, 1, xn) { rep(j, 1, yn) b[j]=0; if (Find(i)) ans++; } printf("%d\n", ans); scanf("%d", &n); } return 0; }