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 <= N, M <= 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
Author: YU, Xiaoyao
Source: The 11th Zhejiang Provincial Collegiate Programming Contest
题意:两种颜色,颜色相同且有公共边的(或者通过另一个相同的颜色连接)为一个连通块,如果翻转其中一个,与它在同一个连通块里的都要改变颜色,求达到相同颜色的最小步数
解题思路:dfs ( 建图) + bfs ( 寻找最优解 ) .
1) dfs( 建图 ) ,因为翻转的时候每翻转连通块中一个整个连通块都翻转,这样你可以将其看成一个有边相连的无向图,每个边的两个顶点颜色都不一样。
2) bfs( 寻找最优解 ) , 建完图后就需要翻转计算最优解,可以枚举从每一点开始翻转所得到的最小步数,那怎样寻找最小步数 ? 假如从 v 这个顶点出发,那么与 v 相邻的顶点颜色必定都与 v 相反,so~> 你只需要把 v的颜色翻转,v与它相邻的所有顶点都是同一个颜色,这时可以把这些顶点看成一个连通块(顶点),再向四周扩展,再次扩展时,周围的颜色必定与此连通块颜色相反,再将它变成与周围顶点相同的颜色,这样又合并成为一个连通块……这样一直进行下去取最大步数。最后从最大步数中取出最小的步数即为最优解
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#include <stack>
#include <map>
#include <climits>
#include <functional>
using namespace std;
#define LL long long
const int INF=0x3f3f3f3f;
int n,m;
char ch[50][50];
int dir[5][2]= {{1,0},{-1,0},{0,1},{0,-1}};
int a[50][50],cnt;
bool vis[2000];
vector<int>G[2000];
struct node
{
int x,step;
};
int bfs(int x)
{
int ma=0;
queue<node>q;
node pre,nt;
memset(vis,0,sizeof vis);
pre.x=x;
pre.step=0;
vis[x]=true;
q.push(pre);
while(!q.empty())
{
pre=q.front();
q.pop();
ma=max(ma,pre.step);
int Size=G[pre.x].size();
nt.step=pre.step+1;
for(int i=0; i<Size; i++)
{
nt.x=G[pre.x][i] ;
if(!vis[nt.x])
{
vis[nt.x]=true;
q.push(nt);
}
}
}
return ma;
}
void dfs(int x,int y,int ct)
{
for(int i=0; i<4; i++)
{
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(xx<0||yy<0||xx>=n||yy>=m) continue;
if(ch[xx][yy]==ch[x][y])
{
if(a[xx][yy]==-1)
{
a[xx][yy]=ct;
dfs(xx,yy,ct);
}
}
else
{
if(a[xx][yy]!=-1)
{
G[ct].push_back(a[xx][yy]);
G[a[xx][yy]].push_back(ct);
}
}
}
}
int main()
{
int t;
scanf("%d",&t) ;
while(t--)
{
scanf("%d%d",&n,&m) ;
memset(a,-1,sizeof a) ;
for(int i=0; i<n*m; i++) G[i].clear();
cnt=0;
for(int i=0; i<n; i++)
scanf("%s",ch[i]);
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(a[i][j]==-1)
{
a[i][j]=cnt++;
dfs(i,j,cnt-1);
}
}
}
int ans=INF;
for(int i=0; i<cnt; i++)
{
int ma=bfs(i);
ans=min(ans,ma);
}
printf("%d\n",ans) ;
}
return 0 ;
}