Codevs1022题解---匈牙利算法

题目描述 Description

有一个N×M的单位方格中,其中有些方格是水塘,其他方格是陆地。如果要用1×2的矩阵区覆盖(覆盖过程不容许有任何部分重叠)这个陆地,那么最多可以覆盖多少陆地面积。

输入描述 Input Description

输入文件的第一行是两个整数NM  (1<=NM<=100),第二行为一个整数K( K<=50),接下来的K行,每行两个整数X,Y表示K个水塘的行列位置。(1<=X<=N1<=Y<=M)。

输出描述 Output Description

输出所覆盖的最大面积块(1×2面积算一块)。

样例输入 Sample Input

4 4

6

1 1

1 4

2 2

4 1

4 2

4 4

样例输出 Sample Output

4

 

这道题目中的一个矩阵会覆盖2块陆地,所以我们可以通过为陆地编号的方式将陆地分为两组,相邻的两块陆地间有一条边相连,即可进行二分图最大匹配的查找,注意需要排除水塘。

献上代码

 1 #include <cstdio>
 2 #include <cstring>
 3 bool wat[101][101],map[101][101],use[101][101];
 4 int n,m,k,ans,px,py;
 5 int from[101][101][2],t[5]={0,1,-1,0,0},tt[5]={0,0,0,1,-1};
 6 bool find(int x,int y)
 7 {
 8     for(int i=1;i<=4;i++)//向四周搜索可行的增广路
 9     {
10         px=x+t[i];py=y+tt[i];
11         if(px<=0||px>n||py<=0||py>m||wat[px][py])continue;
12         if (!wat[px][py] && !use[px][py]&& !map[px][py])//排除水塘
13         {
14             use[px][py]=true;
15             if((!from[px][py][0])||(find(from[px][py][0],from[px][py][1])))
16             {
17                 from[px][py][0]=x;
18                 from[px][py][1]=y;
19                 return true;
20             } 
21         }
22     }
23     return false;
24 }
25 int main()
26 {
27     scanf("%d%d%d",&n,&m,&k);
28     int x,y;
29     for(int i=1;i<=k;i++)
30     {
31         scanf("%d%d",&x,&y);
32         wat[x][y]=true;
33     }
34     for(int i=1;i<=n;i++)
35         for(int j=1;j<=m;j++)
36             if((i % 2 && j % 2) || (i%2==0 && j%2==0))map[i][j]=1;//选出红色的1
37     for(int i=1;i<=n;i++)
38     {
39         for(int j=1;j<=m;j++)
40         {
41             if(!wat[i][j]&&map[i][j])
42             {
43                 memset(use, 0, sizeof(use));
44                 if(find(i,j))ans++;
45             }
46         }
47     }
48     printf("%d",ans);
49     return 0;
50 }

 

posted @ 2016-08-14 23:43  c0per  阅读(761)  评论(0编辑  收藏  举报