题目链接: hdu 1507
题目大意: 给出NxM的地图,地图上有空地和草地
用1x2的草地去覆盖空地,问最多覆盖数
解题思路: 首先1x2的草地,涉及到两个相邻的空地
若先选择第一个空地,则在没有草地的前提下第二个空地有四种选择
分别从图中不同块任意一个顶点出发,黑白染色,黑色即是第一个空地,白色即是第二个空地
因为只能选择四个方向,所以不存在相邻的空地存在同一种颜色
黑色的空地为X集合,白色的空地为Y集合,问题转化为X和Y集合的最大匹配数
代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 101 int kk,Map[MAX][MAX],n,m,edge[51][51],cx[51],cy[51],Fx[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; int visit[51],color[51]; struct snode{ int x,y; }listb[MAX*MAX-51]; int DFS(int u) //DFS增广 { int i; for(i=1;i<=kk;i++) { if(edge[u][i]&&!visit[i]&&!color[i]) { visit[i]=1; if(!cy[i]||DFS(cy[i])) { cx[u]=i; cy[i]=u; return 1; } } } return 0; } void Color(int x,int y,int k) //交叉染色 { int i,tempx,tempy; for(i=0;i<4;i++) { tempx=x+Fx[i][0]; tempy=y+Fx[i][1]; if(tempx<=0||tempx>n||tempy<=0||tempy>m) continue; if(Map[tempx][tempy]!=-1&&color[Map[tempx][tempy]]==-1) { color[Map[tempx][tempy]]=!k; Color(tempx,tempy,!k); } } } int main() { int a,b,i,j,j1,k,tempx,tempy,sum; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) break; scanf("%d",&k); kk=sum=0; memset(cx,0,sizeof(cx)); memset(cy,0,sizeof(cy)); memset(Map,0,sizeof(Map)); memset(listb,0,sizeof(listb)); memset(edge,0,sizeof(edge)); memset(color,-1,sizeof(color)); for(i=1;i<=k;i++) { scanf("%d%d",&a,&b); Map[a][b]=-1; } for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { if(Map[i][j]==0) { ++kk; listb[kk].x=i,listb[kk].y=j; Map[i][j]=kk; } } } memset(edge,0,sizeof(edge)); for(i=1;i<=n;i++) //黑白染色 { for(j=1;j<=m;j++) { if(Map[i][j]!=-1&&color[Map[i][j]]==-1) //未染色 { color[Map[i][j]]=0; Color(i,j,0); } } } for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { for(j1=0;j1<4;j1++) { tempx=i+Fx[j1][0]; tempy=j+Fx[j1][1]; if(tempx<=0||tempx>n||tempy<=0||tempy>m) continue; if(Map[tempx][tempy]!=-1&&color[Map[i][j]]&&!color[Map[tempx][tempy]]) { edge[Map[i][j]][Map[tempx][tempy]]=1; //单向图,黑->白边 } } } } for(i=1;i<=kk;i++) { if(!cx[i]&&color[i]) { memset(visit,0,sizeof(visit)); sum+=DFS(i); } } memset(visit,0,sizeof(visit)); printf("%d\n",sum); for(i=1;i<=kk;i++) { if(cx[i]&&!visit[i]&&!visit[cx[i]]) { visit[i]=visit[cx[i]]=1; printf("(%d,%d)--(%d,%d)\n",listb[i].x,listb[i].y,listb[cx[i]].x,listb[cx[i]].y); } } puts(""); } return 0; }