1022 覆盖
题目描述 Description
有一个N×M的单位方格中,其中有些方格是水塘,其他方格是陆地。如果要用1×2的矩阵区覆盖(覆盖过程不容许有任何部分重叠)这个陆地,那么最多可以覆盖多少陆地面积。
输入描述 Input Description
输入文件的第一行是两个整数N,M (1<=N,M<=100),第二行为一个整数K( K<=50),接下来的K行,每行两个整数X,Y表示K个水塘的行列位置。(1<=X<=N,1<=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
解题思路 将该题目转化为二分图使用匈牙利算法解
n*m的格子可以按顺序分成0 1的图
如
0101010101
1010101010
0101010101
1010101010
一个点的位置(x,y)可以和周围的点(x+1,y),(x,y-1),(x,y+1),(x-1,y)进行两两匹配
有水的地方直接跳过
得出最后最多有多少对匹配成功的点
即答案所求 多少可以覆盖多少板子
#include<iostream> #include<cstring> using namespace std; int n,m,k,a,b,ans; bool water[101][101]; bool ok[101][101]; int linkx[101][101]; int linky[101][101]; int dx[]={0,0,1,-1}; int dy[]={1,-1,0,0}; bool dfs(int x,int y) { if(water[x][y])return false; for(int i=0;i<4;i++) { int xx=x+dx[i]; int yy=y+dy[i]; if(xx>0&&yy>0&&yy<=m&&xx<=n&&water[xx][yy]==false&&ok[xx][yy]==false) { ok[xx][yy]=true; if(linkx[xx][yy]==0||dfs(linkx[xx][yy],linky[xx][yy])) { linkx[xx][yy]=x; linky[xx][yy]=y; return true; } } } return false; } int main() { cin>>n>>m>>k; for(int i=0;i<k;i++) { cin>>a>>b; water[a][b]=true; } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { memset(ok,0,sizeof(ok)); if(i%2==j%2) if(dfs(i,j)) ans++; } cout<<ans<<endl; return 0; }