题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3781
题意: 给出一个N*M的棋盘,每个格子有白色或者黑色的棋子,若2个同色棋子相邻,则称他们是联通的。每次可以选择一大块联通的棋子进行翻转,使整块变成另一种颜色,求最少要操作多少次才能使得整个棋盘的颜色一致
分析: 题中很明显地提到了联通这个概念,我们首先会想到将相同颜色相邻的棋子即一个联通块缩成一个点,然后不同点之间开始建边。每一次翻转相当于从一个点开始进行BFS,这个点所能抵达的其它点和当前点都会变成同一个颜色,而若要将整个棋盘变成同一种颜色,我们需要讲BFS进行到底,即搜索到不能再搜索,这个深度就是从BFS起点开始到整个棋盘颜色一致所需要的操作数,所以我们可以从每个点开始进行一次BFS,最后取最小值即可
AC代码:
/*************************************************************************
> File Name: test.cpp
> Author: Akira
> Mail: qaq.febr2.qaq@gmail.com
************************************************************************/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <bitset>
#include <queue>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <set>
#include <list>
#include <ctime>
#include <climits>
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Sqr(a) ((a)*(a))
using namespace std;
#define MaxN 100000
#define MaxM MaxN*10
#define INF 0x3f3f3f3f
#define bug cout<<88888888<<endl;
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
template<typename _> inline void scan(_& t)
{
int c;
while((c = getchar()) < '0' || c > '9');
t = c - '0';
while((c = getchar()) >= '0' && c <= '9') t = t * 10 + c - '0';
}
template<typename _> inline void print(_ x)
{
int len = 0, p[20];
if(x < 0) putchar('-'), x = -x;
while(x) p[++len] = x % 10, x /= 10;
if(!len) p[++len] = 0;
while(len) putchar(p[len--] + '0');
}
int T;
int N,M;
char Map[41][41];
int id[41][41];
int Num;
vector<int> V[1700];
set<int> S[1700];
int dir[4][2] = {{1,0}, {0,1}, {-1,0}, {0,-1}};
bool check(int x, int y)
{
if(x<0||x>=N||y<0||y>=M) return false;
else return true;
}
void DFS(int x, int y)
{
id[x][y] = Num;
for(int i=0;i<4;i++)
{
int xx = x + dir[i][0];
int yy = y + dir[i][1];
if(check(xx,yy))
{
if( Map[xx][yy] == Map[x][y] && id[xx][yy]==0)
{
DFS(xx,yy);
}
else if( Map[xx][yy] != Map[x][y] && id[xx][yy]!=0)
{
int t = id[xx][yy];
if (!S[Num].count(t))
{
S[Num].insert(t);
V[t].push_back(Num);
V[Num].push_back(t);
}
}
}
}
}
int vis[1700];
int BFS(int s)
{
CLR(vis);
vis[s] = 1;
queue<int> Q;
queue<int> D;
Q.push(s);
D.push(0);
int ans = 0;
while(!Q.empty())
{
int tmp = Q.front();Q.pop();
int d = D.front();D.pop();
ans = MAX(ans, d);
for(int i=0;i<V[tmp].size();i++)
{
int v = V[tmp][i];
if(!vis[v])
{
vis[v] = 1;
Q.push(v);
D.push(d+1);
}
}
}
return ans;
}
void init()
{
CLR(id);
Num = 0;
}
int main()
{
scanf("%d", &T);
while(T--)
{
init();
scanf("%d%d", &N, &M);
for(int i=0;i<N;i++)
{
scanf("%s", Map[i]);
}
for(int i=0;i<N;i++)
{
for(int j=0;j<M;j++)
{
if(!id[i][j])
{
id[i][j] = ++Num;
V[Num].clear();
S[Num].clear();
DFS(i,j);
}
}
}
int ans = INF;
for(int i=1;i<=Num;i++)
{
int tmp = BFS(i);
ans = MIN(ans, tmp);
}
printf("%d\n", ans);
}
//system("pause");
}
/*
1345
2 2
OX
OX
3 3
XOX
OXO
XOX
*/