ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【最短路+bfs+缩点】Paint the Grid Reloaded ZOJ - 3781

2020-05-20 12:54:28  阅读:175  来源: 互联网

标签:缩点 tmp 3781 int Reloaded ++ while book front


题目:

Leo has a grid with N rows and M columns. All cells are painted with either black or white initially.

Two cells A and B are called connected if they share an edge and they are in the same color, or there exists a cell C connected to both A and B.

Leo wants to paint the grid with the same color. He can make it done in multiple steps. At each step Leo can choose a cell and flip the color (from black to white or from white to black) of all cells connected to it. Leo wants to know the minimum number of steps he needs to make all cells in the same color.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

The first line contains two integers N and M (1 <= NM <= 40). Then N lines follow. Each line contains a string with N characters. Each character is either 'X' (black) or 'O' (white) indicates the initial color of the cells.

Output

For each test case, output the minimum steps needed to make all cells in the same color.

Sample Input

2
2 2
OX
OX
3 3
XOX
OXO
XOX

Sample Output

1
2

Hint

For the second sample, one optimal solution is:

Step 1. flip (2, 2)

XOX
OOO
XOX

Step 2. flip (1, 2)

XXX
XXX
XXX

大意:

给定的图片有两种颜色,我们可以任选一个色块将其颜色改变,求最少几次能把图片变为纯色。

题解:

题目的数据最大是40,不算很大,大概率可暴力

首先因为图片形式的数据并不好处理,所以我们把它分为最小的影响部分,把每一个单独的色块缩成一个点,边界相邻的变成一条线,这样就吧一个图片转换成图了。

实现方法:先用bfs对每个色块涂色并编号,然后再用bfs遍历色块,转换成图。两者复杂度都很低O(n*m)

然后问题就化简为将图变为纯色的最小步骤了。

这时图中相邻的点一定是异色的,因为如果两点相邻切同色就会被归为一点。

再思考涂色的方法,对任意点转色后,相当于把该点的所有邻点变为同色,也就是说相当于把所有邻点缩为一个新点,之前被缩的点的所有边变为新点的边。假设一个点的邻点的平均值是x,新点的邻点的平均值就是x*x。根据贪心原则下一个选择转色的点也应该是新点。所以转色就变成了从某点开始图的深度。

这样题目就变成了,求图深度的最小值。

实现方法:bfs遍历各点。

AC代码:

#include<iostream>
#include<queue>
#include<cstring>
#include<vector>
#define clear(x) {memset(x, 0, sizeof(x));}
using namespace std;
struct point {
    int x, y;
};
int dx[] = { 0,0,1,-1 };
int dy[] = { 1,-1,0,0 };
char s[100][100];
int book[100][100];
int book2[100][100];
vector<int>e[1605];
int book3[1605];
int k, n, m,ma;
queue<point>q;
int bfs1(point x) {
    if (book[x.x][x.y] != 0)return 0;
    while (!q.empty())q.pop();
    q.push(x);
    book[x.x][x.y] = k;
    while (!q.empty()) {
        for (int i = 0; i < 4; i++) {
            point tmp = q.front();
            tmp.x += dx[i];
            tmp.y += dy[i];
            if (tmp.x < 0 || tmp.x >= n)continue;
            if (tmp.y < 0 || tmp.y >= m)continue;
            if (book[tmp.x][tmp.y] == 0&&s[q.front().x][q.front().y]==s[tmp.x][tmp.y]) {
                book[tmp.x][tmp.y] = k;
                q.push(tmp);
            }
        }
        q.pop();
    }
    return 1;
}

void bfs2(point x){
    if (book2[x.x][x.y] != 0)return;
    while (!q.empty())q.pop();
    q.push(x);
    book2[x.x][x.y] = 1;
    while (!q.empty()) {
        for (int i = 0; i < 4; i++) {
            point tmp = q.front();
            tmp.x += dx[i];
            tmp.y += dy[i];
            if (tmp.x < 0 || tmp.x >= n)continue;
            if (tmp.y < 0 || tmp.y >= m)continue;
            if (book2[tmp.x][tmp.y] == 0 && s[q.front().x][q.front().y] == s[tmp.x][tmp.y]) {
                book2[tmp.x][tmp.y] = 1;
                q.push(tmp);
            }
            else if (s[q.front().x][q.front().y] != s[tmp.x][tmp.y]) {
                e[book[q.front().x][q.front().y]].push_back(book[tmp.x][tmp.y]);
            }
        }
        q.pop();
    }
}
int bfs3(int top) {
    int max = 0;
    clear(book3);
    while (!q.empty())q.pop();
    q.push({ top,0 });
    book3[top] = 1;
    while (!q.empty()) {
        point tmp = q.front();
        if (tmp.y > max)max = tmp.y;
        for (int i :e[tmp.x]) {
            if (book3[i] == 0) {
                book3[i] = 1;
                q.push({ i,tmp.y + 1 });
            }
        }
        q.pop();
    }
    return max;

}

int main() {
    int t;
    cin >> t;
    while (t--) {
        
        int ans = 1e9;
        k = 1;
        cin >> n >> m;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                cin >> s[i][j];

        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++) 
                if(bfs1({ i,j }))k++;
                
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                bfs2({ i,j });
    

        for (int i = 1; i < k; i++) {
            int tmp = bfs3(i);
            if (tmp < ans)ans = tmp;
        }

        cout << ans << '\n';

        clear(book);
        clear(book2);
        clear(e);
    }



}

 

 

标签:缩点,tmp,3781,int,Reloaded,++,while,book,front
来源: https://www.cnblogs.com/komet/p/12922933.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有