POJ_2446_Chessboard

来源:互联网 发布:子域名与二级域名 编辑:程序博客网 时间:2024/05/04 18:29

题目意思就是一个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 }

我的思路大致是这样:

由于是将棋盘相邻两区域覆盖,所以可将棋盘黑白相间的涂色,然后再挖去相应的洞,这样,将白色的作为一个二分图节点子集,剩下的作为另一个子集,然后相邻的黑白块代表的顶点在二分图中连接起来,然后求出二分图的额最大匹配数,便是最多能够放置的板子。

0 0
原创粉丝点击