POJ 2226 Muddy Fields 二分图(难点在于建图)

题意:给定一个矩阵和它的N行M列,其中有一些地方有水,现在有一些长度任意,宽为1的木板,要求在板不跨越草,用一些木板盖住这些有水的地方,问至少需要几块板子?

思路:首先想到如果没有不准跨越草的条件则跟POJ 3041题意一样(如果想看的话可以点击这里),然而这一题多了个条件,那么将矩阵转化的方式需要改变,不能直接将行列分成两个集合了。需要先查看两遍矩阵,一遍横向查看有无连续‘*’的情况,若连续说明一块板子就可以覆盖,所以标记为同样的数字,反之则不同;同理另一遍纵向查看矩阵连续'*'的情况,处理方式同上。这样就建图完毕了。

  1 #include<cstdio>
  2 
  3 #include<cstring>
  4 
  5 #include<iostream>
  6 
  7 #include<algorithm>
  8 
  9 using namespace std;
 10 
 11  
 12 
 13 const int N = 600;
 14 
 15 int n, m, p, q;
 16 
 17 bool lin[N][N];
 18 
 19 int used[N], arr[N], mark[N][N];
 20 
 21 char map[N][N];
 22 
 23  
 24 
 25 bool find(int x)
 26 
 27 {
 28 
 29     for(int j = 1; j <= q; j++)
 30 
 31     {
 32 
 33         if(lin[x][j] && used[j] == 0)
 34 
 35         {
 36 
 37             used[j] = 1;
 38 
 39             if(arr[j] == 0 || find(arr[j]))
 40 
 41             {
 42 
 43                 arr[j] = x;
 44 
 45                 return true;
 46 
 47             }
 48 
 49         }
 50 
 51     }
 52 
 53     return false;
 54 
 55 }
 56 
 57 
 58 
 59 int main()
 60 
 61 {
 62 
 63     int r, c;
 64 
 65     while(~scanf("%d%d", &n, &m))
 66 
 67     {
 68 
 69         memset(map, '0', sizeof(map));
 70 
 71         for(int i = 0; i < n; i++)
 72 
 73         {
 74 
 75             scanf("%s", &map[i]);
 76 
 77         }
 78 
 79         memset(lin, false , sizeof(lin));
 80 
 81         memset(arr, 0, sizeof(arr));
 82 
 83         p = 0;
 84 
 85         for(int i = 0; i < n; i++)
 86 
 87         {
 88 
 89             for(int j = 0; j < m; j++)
 90 
 91             {
 92 
 93                 if(map[i][j] == '*')
 94 
 95                 {
 96 
 97                     if(map[i][j-1] != '*')//横向查看
 98 
 99                     {
100 
101                         p++;
102 
103                     }
104 
105                     mark[i][j] = p;
106 
107                 }    
108 
109             }
110 
111         }
112 
113         q = 0;
114 
115         for(int j = 0; j < m; j++)
116 
117         {
118 
119             for(int i = 0; i < n; i++)
120 
121             {
122 
123                 if(map[i][j] == '*')
124 
125                 {
126 
127                     if(map[i-1][j] != '*')//纵向查看
128 
129                     {
130 
131                         q++;
132 
133                     }
134 
135                     lin[mark[i][j]][q] = true;//横向已经检查完了可以直接建图了
136 
137                 }
138 
139             }
140 
141         }
142 
143         int all = 0;
144 
145         for(int i = 1; i <= p; i++)
146 
147         {
148 
149             memset(used, 0, sizeof(used));
150 
151             if(find(i))
152 
153                 ++all;
154 
155         }
156 
157         printf("%d\n", all);
158 
159     }
160 
161     return 0;
162 
163 }
View Code

 

posted @ 2018-07-31 21:56  llllrj  阅读(161)  评论(0编辑  收藏  举报