hdu 1045 Fire Net (dfs || 二分图)
2013-11-21 14:02
288 查看
题意:
一个N*N的方格,上面有一些地方是墙。一个blockhouse能往四个方向射击,但不能穿透墙。问最多能放多少blockhouse使他们互不攻击到。
解法:
一、
因为数据范围很小,可以直接暴露dfs枚举所有可能,取最大值。
dfs在这里一个比较简单的实现是,是从(0,0)(这里用0表示)出发,递归到(n-1,n-1)(这里用n*n - 1表示)结束,这样比较好写,思路也很清晰。
二、
用二分图来做。
首先对每一行,每段连续(中间没有wall)的方格编一个号。记为xx
然后对每一列,也用同样的方法编号。记为yy
很明显,xx[i] 与 yy[j]能相连 当且仅当 他们对应的方格中有重叠的。根据这个构边。
求最大匹配即为答案。
一个N*N的方格,上面有一些地方是墙。一个blockhouse能往四个方向射击,但不能穿透墙。问最多能放多少blockhouse使他们互不攻击到。
解法:
一、
因为数据范围很小,可以直接暴露dfs枚举所有可能,取最大值。
dfs在这里一个比较简单的实现是,是从(0,0)(这里用0表示)出发,递归到(n-1,n-1)(这里用n*n - 1表示)结束,这样比较好写,思路也很清晰。
#include <cstdio> #include <cstring> using namespace std; #define RE(i,n) for(int i = 0; i < (n); i++) #define SET(a,x) memset(a,x,sizeof(a)) const int N = 5; char mat ; int ret; int n; int move[4][2] = { {-1,0}, {1,0}, {0,-1}, {0,1} }; bool ok(int x) { return x >= 0 && x < n; } bool valid(int x, int y) { return ok(x) && ok(y); } bool can(int x, int y) { if(mat[x][y] != '.') return false; RE(i,4) { int nx = x + move[i][0]; int ny = y + move[i][1]; while(valid(nx,ny)) { if(mat[nx][ny] == 'X') break; else if(mat[nx][ny] == '#') return false; nx += move[i][0]; ny += move[i][1]; } } return true; } void dfs(int cur, int cnt) { if(cur == n * n) { if(cnt > ret) ret = cnt; return; } int x = cur / n; int y = cur % n; if(can(x,y)) { mat[x][y] = '#'; dfs(cur + 1, cnt + 1); mat[x][y] = '.'; } dfs(cur + 1, cnt); } int main() { while(scanf("%d",&n), n > 0) { RE(i,n) scanf("%s",mat[i]); ret = -1; dfs(0,0); printf("%d\n",ret); } return 0; }
二、
用二分图来做。
首先对每一行,每段连续(中间没有wall)的方格编一个号。记为xx
然后对每一列,也用同样的方法编号。记为yy
很明显,xx[i] 与 yy[j]能相连 当且仅当 他们对应的方格中有重叠的。根据这个构边。
求最大匹配即为答案。
#include <cstdio> #include <cstring> using namespace std; #define RE(i,n) for(int i = 0; i < (n); i++) #define SET(a,x) memset(a,x,sizeof(a)) const int N = 5; char mat ; int hash ; int n; int xx,yy; int head[N*N], ecnt; struct edge { int v,next; edge() { } edge(int _v, int _next) { v = _v; next = _next; } } e[N*N*N*N]; void addedge(int u, int v) { e[ecnt] = edge(v,head[u]); head[u] = ecnt++; } void deal() { xx = yy = 0; RE(i,n) { bool flag = 0; RE(j,n) { if(mat[i][j] == 'X') { hash[i][j] = -1; if(flag) { xx++; flag = 0; } } else { hash[i][j] = xx; flag = 1; } } if(flag) xx++; } SET(head,-1); ecnt = 0; RE(j,n) { bool flag = 0; RE(i,n) { if(mat[i][j] == 'X') { if(flag) { yy++; flag = 0; } } else { addedge(yy,hash[i][j]); flag = 1; } } if(flag) yy++; } } int linky[N*N],vis[N*N]; int hungry(int u) { for(int i = head[u]; i != -1; i = e[i].next) { int v = e[i].v; if(vis[v]) continue; vis[v] = 1; if(linky[v] == -1 || hungry(linky[v])) { linky[v] = u; return 1; } } return 0; } int maxmatch() { int ret = 0; SET(linky,-1); RE(i,yy) { SET(vis,0); if(hungry(i)) ret++; } return ret; } int main() { // freopen("in.txt","r",stdin); while(scanf("%d",&n), n > 0) { RE(i,n) scanf("%s",mat[i]); deal(); printf("%d\n",maxmatch()); } return 0; }
相关文章推荐
- HDU 1045 Fire Net (dfs 或 二分图)
- hdu 1045 Fire Net(DFS)
- hdu 1045 Fire Net(DFS+回溯)
- HDU 1045 Fire Net(DFS)
- hdu 1045(dfs暴搜/缩点+二分图最大匹配(典型行列匹配题))
- hdu 1045 || zoj 1002 Fire Net(搜索:DFS+水题)
- hdu1045——Fire Net(二分图+行列匹配)
- HDU1045 Fire Net 暴力搜索DFS
- HDU 1045 Fire Net(DFS)
- hdu 1045 Fire Net (DFS java)
- HDU 1045 Fire Net (DFS)
- hdu-1045 Fire Net(DFS)
- HDU 1045 Fire Net (二分图的最大匹配)
- HDU 1045 Fire Net(DFS)
- HDU 1045-Fire Net(DFS)
- HDU 1045 Fire Net(DFS)
- 【DFS】hdu 1045 Fire Net
- hdu 1045 && zoj 1002 Fire Net(DFS && 二分图匹配)
- hdu 1045 Fire Net(dfs)
- 【DFS 回溯】HDU 1045 Fire Net