洛谷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 }
洛谷P1263

 

posted @ 2017-09-22 07:59  嘒彼小星  阅读(227)  评论(0编辑  收藏  举报