http://acm.hdu.edu.cn/showproblem.php?pid=4619
根据题意可知,每一个方格可能只被一个骨牌覆盖 可能被两个骨牌覆盖 也可能不被覆盖
有一个骨牌覆盖的方格(单覆盖方格)为我们刚开始要找的方格
遍历 每当找到一个单覆盖方格 我们就将这个方格上的骨牌保留
保留这个骨牌的话 有可能会排斥另一个骨牌 如果有排斥的骨牌的话 就将排斥的骨牌去掉
去掉排斥的骨牌 可能产生新的单覆盖方格,则递归下去
最后把所有单覆盖方格处理完 剩下的可能全是双覆盖方格,如果有的话,剩下的骨牌通过覆盖肯定形成了环
这些双覆盖方格每个都会最终保留半个骨牌
代码:
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<cmath> #include<set> #include<map> #include<stack> #include<vector> #include<algorithm> #include<queue> #include<bitset> #include<deque> #include<numeric> //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; typedef long long ll; typedef unsigned int uint; typedef pair<int,int> pp; const double eps=1e-9; const int INF=0x3f3f3f3f; const ll MOD=1000000007; const int N=110; int X[]={-1,1,0,0}; int Y[]={0,0,1,-1}; int a[N][N]; int d[N][N][4]; int ans; void dfs(int i,int j) { for(int l=0;l<4;++l) if(d[i][j][l]==1) { int x=i+X[l]; int y=j+Y[l]; { d[i][j][l]=0; d[x][y][l^1]=0; --a[i][j]; --a[x][y]; ++ans; if(a[x][y]==1) { for(int r=0;r<4;++r) if(d[x][y][r]==1) { int x1=x+X[r]; int y1=y+Y[r]; { d[x][y][r]=0; d[x1][y1][r^1]=0; --a[x][y]; --a[x1][y1]; if(a[x1][y1]==1) dfs(x1,y1); } } } } } } int main() { //freopen("data.in","r",stdin); int n,m; while(scanf("%d %d",&n,&m)!=EOF) { if(!n&&!m) break; memset(a,0,sizeof(a)); memset(d,0,sizeof(d)); while(n--) { int i,j; scanf("%d %d",&i,&j); d[i][j][1]=1; d[i+1][j][0]=1; ++a[i][j]; ++a[i+1][j]; } while(m--) { int i,j; scanf("%d %d",&i,&j); d[i][j][2]=1; d[i][j+1][3]=1; ++a[i][j]; ++a[i][j+1]; } ans=0; for(int i=0;i<=101;++i) for(int j=0;j<=101;++j) if(a[i][j]==1) { dfs(i,j); } int tmp=0; for(int i=0;i<=101;++i) for(int j=0;j<=101;++j) tmp+=a[i][j]; ans+=tmp/4; printf("%d ",ans); } return 0; }