[Wc]Dface双面棋盘

题目

bzoj1453

题解

不算正解吧,数据不是很严,所以过掉了

很容易想到暴力做法,每次翻转后重新算一遍联通块个数,复杂度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
",ans[1],ans[0]);
        /*
        if(ans[0]==0||ans[1]==0) {printf("-1
");continue;}
        int g=gcd(ans[1],ans[0]);
        if(ans[0]/g==1) {printf("%d
",ans[1]/g);continue;}
        printf("%d/%d
",ans[1]/g,ans[0]/g);
        */
    }
    return 0;
}
原文地址:https://www.cnblogs.com/XYZinc/p/7405338.html