[Wc]Dface双面棋盘
题目
题解
不算正解吧,数据不是很严,所以过掉了
很容易想到暴力做法,每次翻转后重新算一遍联通块个数,复杂度O(n²m),但实际上每次翻转后只有与之相邻的联通块会发生变化,其余地方均无改变,会造成许多重复的计算
考虑每次翻转后只对相邻联通块进行修改,用bfs直接搜(dfs超时)
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#define ll long long
using namespace std;
int n,m,mp[210][210],ans[2];
int fx[]={0,0,0,-1,1};
int fy[]={0,1,-1,0,0};
bool flag[210][210];
int X,Y;
struct node
{
int x,y;
};
void bfs(int x,int y,int f)
{
queue<node> q;
flag[x][y]=1;
node t;t.x=x;t.y=y;
q.push(t);
while(!q.empty())
{
node p=q.front();
q.pop();
for(int i=1;i<=4;i++)
{
int xx=p.x+fx[i],yy=p.y+fy[i];
if(xx>=1&&xx<=n&&yy>=1&&yy<=n)
if(mp[p.x][p.y]==mp[xx][yy]&&!flag[xx][yy])
{
flag[xx][yy]=1;
t.x=xx;t.y=yy;
q.push(t);
}
}
if(f)
{
if(X+1<=n) if(!flag[X+1][Y]&&mp[X+1][Y]==mp[x][y]) continue;
if(X-1>=1) if(!flag[X-1][Y]&&mp[X-1][Y]==mp[x][y]) continue;
if(Y+1<=n) if(!flag[X][Y+1]&&mp[X][Y+1]==mp[x][y]) continue;
if(Y-1>=1) if(!flag[X][Y-1]&&mp[X][Y-1]==mp[x][y]) continue;
return;
}
}
}
int gcd(int x,int y)
{
if(!y) return x;
gcd(y,x%y);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) scanf("%d",&mp[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(!flag[i][j]) {bfs(i,j,0);ans[mp[i][j]]++;}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int x,y;scanf("%d%d",&x,&y);
memset(flag,0,sizeof(flag));
X=x;Y=y;
for(int k=0;k<=4;k++)
{
int xx=x+fx[k],yy=y+fy[k];
if(xx>=1&&xx<=n&&yy>=1&&yy<=n&&!flag[xx][yy])
{bfs(xx,yy,1);ans[mp[xx][yy]]--;}
}
mp[x][y]^=1;
memset(flag,0,sizeof(flag));
for(int k=0;k<=4;k++)
{
int xx=x+fx[k],yy=y+fy[k];
if(xx>=1&&xx<=n&&yy>=1&&yy<=n&&!flag[xx][yy])
{bfs(xx,yy,1);ans[mp[xx][yy]]++;}
}
printf("%d %d\n",ans[1],ans[0]);
/*
if(ans[0]==0||ans[1]==0) {printf("-1\n");continue;}
int g=gcd(ans[1],ans[0]);
if(ans[0]/g==1) {printf("%d\n",ans[1]/g);continue;}
printf("%d/%d\n",ans[1]/g,ans[0]/g);
*/
}
return 0;
}