P1035
时间限制: 1 Sec 内存限制: 128 MB提交: 87 解决: 36
[提交][状态][讨论版]
题目描述
给出一张n*n(n< =100)的国际象棋棋盘,其中被删除了一些点,问可以使用多少1*2的多米诺骨牌进行掩盖。
输入
第一行为n,m(表示有m个删除的格子) 第二行到m+1行为x,y,分别表示删除格子所在的位置 x为第x行 y为第y列
输出
一个数,即最大覆盖格数
样例输入
8 0
样例输出
32
提示
经典问题
建图,比较简单,一般人都想得到,所以一个点与其上下左右的点连边,然后就可以了,求一次二分图最大匹配。
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 8 const int x[4]={0,0,1,-1},y[4]={-1,1,0,0}; 9 10 int n,m; 11 bool map[207][207],flag[70007]; 12 int head[17010],cnt,next[70007],rea[70007]; 13 int fa[17010]; 14 void add(int u,int v) 15 { 16 cnt++; 17 next[cnt]=head[u]; 18 head[u]=cnt; 19 rea[cnt]=v; 20 } 21 bool dfs(int u) 22 { 23 for(int i=head[u];i!=-1;i=next[i]) 24 { 25 int v=rea[i]; 26 if(flag[v]==false) 27 { 28 flag[v]=1; 29 if(fa[v]==-1||dfs(fa[v])) 30 { 31 fa[v]=u; 32 return true; 33 } 34 } 35 } 36 return false; 37 } 38 int solve() 39 { 40 int num=0; 41 memset(fa,-1,sizeof(fa)); 42 for(int i=1;i<=n*n;i++) 43 { 44 memset(flag,false,sizeof(flag)); 45 num+=dfs(i); 46 } 47 return num; 48 } 49 int main() 50 { 51 cnt=0; 52 memset(head,-1,sizeof(head)); 53 memset(map,false,sizeof(map)); 54 scanf("%d%d",&n,&m); 55 for(int i=1;i<=m;i++) 56 { 57 int x,y; 58 scanf("%d%d",&x,&y); 59 map[x][y]=true; 60 } 61 for(int i=1;i<=n;i++) 62 for(int j=1;j<=n;j++) 63 if(!map[i][j]) 64 { 65 int numx=(i-1)*n+j; 66 for(int k=0;k<4;k++) 67 { 68 int xx=i+x[k],yy=j+y[k]; 69 if(xx>=1&&xx<=n&&yy>=1&&yy<=n&&!map[xx][yy]) 70 { 71 int numy=(xx-1)*n+yy; 72 add(numx,numy); 73 } 74 } 75 } 76 printf("%d ",solve()/2); 77 }