• 2014 Super Training #4 E Paint the Grid Reloaded --联通块缩点+BFS


    原题: ZOJ 3781 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3781

    题意:

    给一个n*m的X,O构成的格子,对一个点操作可以使与它相连通的所有一样颜色的格子翻转颜色(X->O或O->X),问给定的矩阵最少操作多少次可以全部变成一样的颜色。

    网上思路:

    每次操作都将本身所在的连通块与和自己相邻的不同颜色的连通块变成同一种颜色,也就是变成一个连通块了,那么要使n次操作后全部变成一样的颜色,也就是从某点出发到达其余所有点。所以先dfs把连通块缩成点,然后相邻的连通块之间建边,枚举以每个点为根的情况,bfs求出每种情况的深度,取最小的即为答案。

    思路很重要,实现起来不难。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #define Mod 1000000007
    using namespace std;
    #define N 44
    
    char ss[N][N];
    int ind[N][N],vis[N][N];
    int now,n,m;
    int inq[1630];
    int dx[4] = {1,0,-1,0};
    int dy[4] = {0,1,0,-1};
    vector<int> G[2001];
    
    struct node
    {
        int dis,ind;
    };
    
    int OK(int nx,int ny)
    {
        if(nx < n && nx >= 0 && ny < m && ny >= 0)
            return 1;
        return 0;
    }
    
    void dfs(int nx,int ny,int now)
    {
        for(int k=0;k<4;k++)
        {
            int kx = nx + dx[k];
            int ky = ny + dy[k];
            if(!OK(kx,ky))
                continue;
            if(ss[kx][ky] == ss[nx][ny])
            {
                if(ind[kx][ky] == -1)
                {
                    ind[kx][ky] = now;
                    dfs(kx,ky,now);
                }
            }
            else if(ind[kx][ky] != -1) //已经有标号,连边
            {
                int v = ind[kx][ky];
                G[v].push_back(now);
                G[now].push_back(v);
            }
        }
    }
    
    int SPFA(int num)
    {
        queue<node> que;
        memset(inq,0,sizeof(inq));
        node S,tmp,now;
        S.dis = 0;
        S.ind = num;
        int res = 0;
        que.push(S);
        inq[num] = 1;
        while(!que.empty())
        {
            tmp = que.front();
            que.pop();
            res = max(res,tmp.dis);
            now.dis = tmp.dis + 1;
            for(int i=0;i<G[tmp.ind].size();i++)
            {
                now.ind = G[tmp.ind][i];
                if(!inq[now.ind])
                {
                    inq[now.ind] = 1;
                    que.push(now);
                }
            }
        }
        return res;
    }
    
    int main()
    {
        int i,j,k;
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            for(i=0;i<n;i++)
                scanf("%s",ss[i]);
            now = 1;
            memset(ind,-1,sizeof(ind));
            for(i=0;i<=n*m;i++)
                G[i].clear();
            for(i=0;i<n;i++)
                for(j=0;j<m;j++)
                    if(ind[i][j] == -1)
                    {
                        ind[i][j] = now;
                        dfs(i,j,now);
                        now++;
                    }
            int ans = Mod;
            for(i=1;i<now;i++)
                ans = min(ans,SPFA(i));
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Python学习(十六)内置函数,递归
    Python学习(十五)json串使用,不固定参数,关键词参数
    Python学习(十四)常量,局部变量,全局变量
    python学习(十三)函数
    python学习(十二)模块
    Python学习(十一)文件指针,文件操作练习,修改文件
    mongodb聚合
    mongodb
    软件测试需要学习哪些课程
    Jmeter的使用和监控分析
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3821925.html
Copyright © 2020-2023  润新知