洛谷P1263 宫廷守卫
P1263 宫廷守卫
题目描述
从前有一个王国,这个王国的城堡是一个矩形,被分为M×N个方格。一些方格是墙,而另一些是空地。这个王国的国王在城堡里设了一些陷阱,每个陷阱占据一块空地。
一天,国王决定在城堡里布置守卫,他希望安排尽量多的守卫。守卫们都是经过严格训练的,所以一旦他们发现同行或同列中有人的话,他们立即向那人射 击。因此,国王希望能够合理地布置守卫,使他们互相之间不能看见,这样他们就不可能互相射击了。守卫们只能被布置在空地上,不能被布置在陷阱或墙上,且一 块空地只能布置一个守卫。如果两个守卫在同一行或同一列,并且他们之间没有墙的话,他们就能互相看见。(守卫就像象棋里的车一样)
你的任务是写一个程序,根据给定的城堡,计算最多可布置多少个守卫,并设计出布置的方案。
输入输出格式
输入格式:第一行两个整数M和N(1≤M,N≤200),表示城堡的规模。
接下来M行N列的整数,描述的是城堡的地形。第i行j列的数用ai,j表示。
ai,j=0,表示方格[i,j]是一块空地;
ai,j=1,表示方格[i,j]是一个陷阱;
ai,j=2,表示方格[i,j]是墙。
输出格式:第一行一个整数K,表示最多可布置K个守卫。
此后K行,每行两个整数xi和yi,描述一个守卫的位置。
输入输出样例
输入样例#1:
3 4 2 0 0 0 2 2 2 1 0 1 0 2
输出样例#1:
2 1 2 3 3
说明
样例数据如图5-2(黑色方格为墙,白色方格为空地,圆圈为陷阱,G表示守卫)
由@zhouyonglong提供SPJ
【题解】
空间开到2000疯狂TLE,开到3000T的更多,然后改成200
A了
我******
二分图最大匹配。把行列的01连通块标号,每个0都是连接行列的边
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm> 6 7 inline void read(int &x) 8 { 9 x = 0;char ch = getchar(), c = ch; 10 while(ch < '0' || ch > '9')c = ch, ch = getchar(); 11 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar(); 12 if(c == '-')x = -x; 13 } 14 15 const int MAXN = 200 + 10; 16 17 int gg[MAXN][MAXN]; 18 int lk[MAXN * MAXN], b[MAXN * MAXN], g[MAXN][MAXN], r, c, n, m, tmp, line[MAXN][MAXN], row[MAXN][MAXN]; 19 20 struct Edge 21 { 22 int u,v,next; 23 Edge(int _u, int _v, int _next){u = _u;v = _v;next = _next;} 24 Edge(){} 25 }edge[MAXN * MAXN]; 26 int head[MAXN * MAXN],cnt; 27 void insert(int a, int b) 28 { 29 edge[++cnt] = Edge(a,b,head[a]); 30 head[a] = cnt; 31 } 32 33 int dfs(int u) 34 { 35 for(register int pos = head[u];pos;pos = edge[pos].next) 36 { 37 int v = edge[pos].v; 38 if(!b[v]) 39 { 40 b[v] = 1; 41 if(lk[v] == -1 || dfs(lk[v])) 42 { 43 lk[v] = u; 44 return 1; 45 } 46 } 47 } 48 return 0; 49 } 50 51 int xiongyali() 52 { 53 int ans = 0; 54 memset(lk, -1, sizeof(lk)); 55 for(register int i = 1;i <= n;++ i) 56 { 57 memset(b, 0, sizeof(b)); 58 ans += dfs(i); 59 } 60 return ans; 61 } 62 63 int main() 64 { 65 read(r), read(c); 66 register int i,j; 67 for(i = 1;i <= r;++ i) 68 for(j = 1;j <= c;++ j) 69 read(gg[i][j]); 70 register int tot = 0; 71 for(i = 1;i <= r;++ i) 72 for(j = 1;j <= c;++ j) 73 if(gg[i][j] != 2) 74 { 75 ++ tot; 76 while(gg[i][j] != 2 && j <= c)row[i][j] = tot,++ j; 77 } 78 n = tot; 79 tot = 0; 80 for(j = 1;j <= c;++ j) 81 for(i = 1;i <= r;++ i) 82 if(gg[i][j] != 2) 83 { 84 ++ tot; 85 while(gg[i][j] != 2 && i <= r)line[i][j] = tot, ++ i; 86 } 87 m = tot; 88 for(i = 1;i <= r;++ i) 89 for(j = 1;j <= c;++ j) 90 if(gg[i][j] == 0) 91 insert(row[i][j], line[i][j]); 92 printf("%d\n", xiongyali()); 93 for(register int k = 1;k <= m;++ k) 94 { 95 int flag = 0; 96 if(lk[k] != -1) 97 { 98 for(i = 1;i <= r;++ i) 99 { 100 for(j = 1;j <= c;++ j) 101 { 102 if(row[i][j] == lk[k] && line[i][j] == k && gg[i][j] == 0) 103 { 104 printf("%d %d\n", i, j); 105 flag = 1; 106 break; 107 } 108 } 109 if(flag)break; 110 } 111 } 112 } 113 return 0; 114 }