题目意思就是一个M*N的有洞棋盘棋盘上,用1*2的板子去覆盖没有洞的地方,要求板子不能重叠,最终能否将棋盘完整覆盖。
代码:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #define MAX 35 5 6 struct z 7 { 8 int color; 9 int ct; 10 }; 11 struct z chess[MAX*MAX]; 12 int lc,rc; 13 int m,n;a 14 __int64 hole[MAX*MAX]; 15 __int64 G[MAX*MAX][MAX*MAX]; 16 __int64 link[MAX*MAX]; 17 __int64 vis[MAX*MAX]; 18 int zero=0,one=0;/*分别记录0,1的个数*/ 19 20 int find(int); 21 void bin_map(void); 22 23 int main(void) 24 { 25 int k,i,j; 26 int x,y; 27 scanf("%d%d%d",&m,&n,&k); 28 for(i=0; i<k; i++) 29 { 30 scanf("%d%d",&x,&y); 31 hole[n*(y-1)+x]=1; 32 } 33 if(n&1) 34 for(j=1,i=1; i<=m*n; i++) 35 { 36 if(hole[i]==0) 37 { 38 chess[i].color=j=!j; 39 if(j) 40 chess[i].ct=++one; 41 else 42 chess[i].ct=++zero; 43 } 44 else 45 { 46 chess[i].color=-1; 47 j=!j; 48 } 49 } 50 else 51 for(j=1,i=1; i<=m*n; i++) 52 { 53 if(hole[i]==0) 54 { 55 chess[i].color=!j; 56 if(!j) 57 chess[i].ct=++one; 58 else chess[i].ct=++zero; 59 } 60 else 61 chess[i].color=-1; 62 if(i%n) 63 j=!j; 64 } 65 bin_map(); 66 int ans=0; 67 for(i=1; i<=zero; i++) 68 { 69 memset(vis,0,sizeof(vis)); 70 if(find(i)) 71 ans++; 72 } 73 if(2*ans==m*n-k) 74 puts("YES"); 75 else puts("NO"); 76 return 0; 77 } 78 79 void bin_map(void) 80 { 81 int i; 82 for(i=1; i<=m*n; i++) 83 { 84 if(chess[i].color==0) 85 { 86 if(i%n!=1&&chess[i-1].color==1) 87 G[chess[i].ct][chess[i-1].ct]=1; 88 if(i%n&&chess[i+1].color==1) 89 G[chess[i].ct][chess[i+1].ct]=1; 90 if(i>n&&chess[i-n].color==1) 91 G[chess[i].ct][chess[i-n].ct]=1; 92 if(i<=m*n-n&&chess[i+n].color==1) 93 G[chess[i].ct][chess[i+n].ct]=1; 94 } 95 } 96 } 97 int find(int x) 98 { 99 int i; 100 for(i=1; i<=one; i++) 101 { 102 if(G[x][i]&&!vis[i]) 103 { 104 vis[i]=1; 105 if(link[i]==0||find(link[i])) 106 { 107 link[i]=x; 108 return 1; 109 } 110 } 111 } 112 return 0; 113 }
我的思路大致是这样:
由于是将棋盘相邻两区域覆盖,所以可将棋盘黑白相间的涂色,然后再挖去相应的洞,这样,将白色的作为一个二分图节点子集,剩下的作为另一个子集,然后相邻的黑白块代表的顶点在二分图中连接起来,然后求出二分图的额最大匹配数,便是最多能够放置的板子。