[poj2446]Chessboard

Description

给定一个m×n的棋盘,上面有k个洞,求是否能在不重复覆盖且不覆盖到洞的情况下,用2×1的卡片完全覆盖棋盘。

Input

第一行有三个整数n,m,k(0<m,n<=32, 0<=k<m×n),m表示行数,n表示列数。

接下来k行,每行两个整数y,x,表示(x,y)上有个洞。

Output

如果能覆盖,输出YES;否则输出NO

Sample Input

4 3 2

2 1

3 3

Sample Output

YES

Solution

32×32的范围如果暴搜剪枝能力比较强的人也许能过吧,但是我并没有那个能力。

2×1的卡片去覆盖的话,就是两个相邻的格子为一对,且每个格子只能属于一对(有洞的格子不属于任何一对)

怎么有点像二分图匹配?那就想想怎么构图吧。

定义两格子相邻当且仅当它们有一条公共边时。

那么两个相邻的格子就得在不同集合里,按这样分正好能分成两个集合。

然后两个可放卡片的相邻格子连一条边,这样二分图就构成功了。

 1 #include<set> 
 2 #include<cmath>
 3 #include<ctime>
 4 #include<queue>
 5 #include<stack>
 6 #include<cstdio>
 7 #include<vector>
 8 #include<cstring>
 9 #include<cstdlib>
10 #include<iostream>
11 #include<algorithm>
12 #define D 5 
13 #define N 35
14 #define K 513
15 #define M 2049
16 using namespace std;
17 struct graph{
18     int nxt,to;
19 }e[M];
20 int x[D]={0,0,0,1,-1},y[D]={0,1,-1,0,0};
21 int g[K],fr[N*N],m,n,k,cnt,tot,sum;
22 bool b[N][N],u[N*N];
23 inline void addedge(int x,int y){
24     e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;
25 }
26 inline bool match(int k){
27     for(int i=g[k];i;i=e[i].nxt)
28         if(!u[e[i].to]){
29             u[e[i].to]=true;
30             if(!fr[e[i].to]||match(fr[e[i].to])){
31                 fr[e[i].to]=k;return true;
32             }
33         }
34     return false;
35 }
36 inline bool hungary(){
37     for(int i=1;i<=tot;i++){
38         memset(u,0,sizeof(u));
39         if(!match(i)) return false;
40     }
41     return true;
42 }
43 inline void init(){
44     scanf("%d%d%d",&m,&n,&k);
45     for(int i=1;i<=m;i++)
46         for(int j=1;j<=n;j++)
47             b[i][j]=true;
48     for(int i=1,j,l;i<=k;i++){
49         scanf("%d%d",&j,&l);
50         b[l][j]=false;
51     }
52     for(int i=1;i<=m;i++)
53         for(int j=!(i&1)+1;j<=n;j+=2)
54             if(b[i][j]){
55                 ++tot;
56                 for(int l=1;l<D;l++)
57                     if(b[i+x[l]][j+y[l]])
58                         addedge(tot,(i+x[l]-1)*n+j+y[l]);
59             }
60     for(int i=1;i<=m;i++)
61         for(int j=(i&1)+1;j<=n;j+=2)
62             if(b[i][j]) sum++;
63     if(sum==tot&&hungary()) printf("YES
");
64     else printf("NO
");
65 }
66 int main(){
67     freopen("chessboard.in","r",stdin);
68     freopen("chessboard.out","w",stdout);
69     init();
70     fclose(stdin);
71     fclose(stdout);
72     return 0;
73 }

 

 

原文地址:https://www.cnblogs.com/AireenYe/p/5658005.html