首页 > 代码库 > 2171 棋盘覆盖
2171 棋盘覆盖
2171 棋盘覆盖
时间限制: 1 s
空间限制: 32000 KB
题目等级 : 黄金 Gold
题目描述 Description
给出一张n*n(n<=100)的国际象棋棋盘,其中被删除了一些点,问可以使用多少1*2的多米诺骨牌进行掩盖。
输入描述 Input Description
第一行为n,m(表示有m个删除的格子)
第二行到m+1行为x,y,分别表示删除格子所在的位置
x为第x行
y为第y列
输出描述 Output Description
一个数,即最大覆盖格数
样例输入 Sample Input
8 0
样例输出 Sample Output
32
数据范围及提示 Data Size & Hint
经典问题
分类标签 Tags 点此展开
暂无标签
匈牙利
/*其实如果把国际棋盘白色的看成集合A,黑的看成集合B。//每个合法的格子与相邻的合法格子有无向边(合法就是没有被删除),//这种最大匹配就是所谓的最大覆盖数。*/#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int dx[]={0,0,1,-1};const int dy[]={1,-1,0,0};const int N=1e4+10;const int V=110;int n,m,num,ans,tot,mp[V][V],id[V][V],match[N],yy[N],head[N],next[N<<2],list[N<<2]; void add(int x,int y){ list[++tot]=y; next[tot]=head[x]; head[x]=tot;}bool inside(int x,int y){ return x>0&&x<=n&&y>0&&y<=n;}bool hungary(int x){ for(int i=head[x];i;i=next[i]){ if(!yy[list[i]]){ yy[list[i]]=1; if(!match[list[i]]||hungary(match[list[i]])){ match[list[i]]=x; return 1; } } } return 0;}void mapping(){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ id[i][j]=++num; } } for(int i=1;i<=n;i++){ for(int j=1+!(i&1);j<=n;j+=2){ if(mp[i][j]) continue; for(int k=0;k<4;k++){ int nx=i+dx[k],ny=j+dy[k]; if(inside(nx,ny)&&!mp[nx][ny]){ add(id[i][j],id[nx][ny]); } } } }}void solve(){ for(int i=1;i<=n;i++){ for(int j=1+!(i&1);j<=n;j+=2){ if(mp[i][j]) continue; memset(yy,0,sizeof yy); if(hungary(id[i][j])) ans++; } } printf("%d",ans);}int main(){ scanf("%d%d",&n,&m); for(int i=1,x,y;i<=m;i++) scanf("%d%d",&x,&y),mp[x][y]=1; mapping(); solve(); return 0;}
网络流
/*思路:我们可以对棋盘进行染,黑白相间,即相临两格不同色,这样染完色,我们就可以将同种颜色的格子作为一个集合,另外一种颜色作为一个集合,然后相邻格子间存在边的关系 (当然得排除挖去的部分)。求二分图最大匹配*/#include<cstdio>#include<iostream>using namespace std;const int dx[]={0,0,1,-1};const int dy[]={1,-1,0,0};const int N=210;const int M=N*N;const int inf=0x3f3f3f3f;int n,m,S,T,num,id[N][N],mp[N][N],head[M],dis[M],q[M*5];struct node{ int v,next,cap;}e[M*10];int tot=1;void add(int x,int y,int z){ e[++tot].v=y;e[tot].cap=z;e[tot].next=head[x];head[x]=tot; e[++tot].v=x;e[tot].cap=0;e[tot].next=head[y];head[y]=tot;}bool bfs(){ for(int i=S;i<=T;i++) dis[i]=inf; int h=0,t=1; q[t]=S;dis[S]=0; while(h!=t){ int x=q[++h]; for(int i=head[x];i;i=e[i].next){ int v=e[i].v; if(e[i].cap&&dis[v]>dis[x]+1){ dis[v]=dis[x]+1; if(v==T) return 1; q[++t]=v; } } } return dis[T]<inf;}int dfs(int x,int f){ if(x==T) return f; int used=0,t; for(int i=head[x];i;i=e[i].next){ int v=e[i].v; if(e[i].cap&&dis[v]==dis[x]+1){ t=dfs(v,min(f,e[i].cap)); e[i].cap-=t;e[i^1].cap+=t; f-=t;used+=t; if(!f) return used; } } dis[x]=0; return used;}int dinic(){ int res=0; while(bfs()) res+=dfs(S,inf); return res;}void mapping(){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ id[i][j]=++num; } } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(mp[i][j]) continue; if((i+j)&1^1){ add(S,id[i][j],1); for(int k=0;k<4;k++){ int nx=i+dx[k],ny=j+dy[k]; if(nx<1||nx>n||ny<1||ny>n||mp[nx][ny]) continue; add(id[i][j],id[nx][ny],1); } } else{ add(id[i][j],T,1); } } }}int main(){ scanf("%d%d",&n,&m);S=0;T=n*n+1; for(int i=1,x,y;i<=m;i++) scanf("%d%d",&x,&y),mp[x][y]=1; mapping(); printf("%d",dinic()); return 0;}
2171 棋盘覆盖
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。