这个题郁闷了。。。
卡了好长时间,不过还好过了。将不相邻的点分为一组,也就是横纵坐标相加为奇数的为一组,另外为一组,然后相邻的在两组中间连一条线,最后求最大匹配
code:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int dx[]={-1,0,1,0}; const int dy[]={0,-1,0,1}; struct node { int no,x,y; }left[52],right[52]; int n,m,k,cnt; bool graph[52][52]; bool map[102][102]; int No[102][102]; int lcnt,rcnt; bool vis[52]; int link[52]; bool find(int x) { int y; for(y=1;y<=rcnt;y++) { int no=right[y].no; if(graph[x][no] && !vis[no]) { vis[no]=true; if(!link[no] || find(link[no])) { link[no]=x; return true; } } } return false; } int main() { int i,j,x,y; while(~scanf("%d%d",&n,&m) && (n+m)) { scanf("%d",&k); cnt=lcnt=rcnt=0; memset(map,0,sizeof(map)); memset(graph,0,sizeof(graph)); memset(link,0,sizeof(link)); memset(No,0,sizeof(No)); for(i=1;i<=k;i++) { scanf("%d%d",&x,&y); map[x][y]=1; } for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { if(!map[i][j]) { No[i][j]=++cnt; if((i+j)&1) { left[++lcnt].no=cnt; left[lcnt].x=i; left[lcnt].y=j; } else { right[++rcnt].no=cnt; right[rcnt].x=i; right[rcnt].y=j; } } } } for(i=1;i<=lcnt;i++) { for(j=0;j<4;j++) { //printf("no:%d x:%d y:%d \n",left[i].no,left[i].x,left[i].y); int nx=left[i].x+dx[j]; int ny=left[i].y+dy[j]; if(No[nx][ny]!=0) { //printf(" nx:%d ny:%d no:%d\n",nx,ny,No[nx][ny]); graph[left[i].no][No[nx][ny]]=1; } } } // for(i=1;i<=lcnt;i++) // { // printf("left %d %d %d \n",left[i].no,left[i].x,left[i].y); // } // for(i=1;i<=50;i++) // { // for(j=1;j<=50;j++) // if(graph[i][j]) // printf("link %d %d \n",i,j); // } int ans=0; for(i=1;i<=lcnt;i++) { memset(vis,0,sizeof(vis)); if(find(left[i].no)) ans++; } printf("%d\n",ans); for(i=1;i<=rcnt;i++) { int no=right[i].no; if(link[no]) { for(j=1;j<=lcnt;j++) { if(left[j].no==link[no]) printf("(%d,%d)--(%d,%d)\n",left[j].x,left[j].y,right[i].x,right[i].y); } } } puts(""); } return 0; }