问题描述
你有一个n*m的矩形,一开始所有格子都是白色,然后给出一个目标状态的矩形,有的地方是白色,有的地方是黑色,你每次可以选择一个连通块(四连通块,且不要求颜色一样)进行染色操作(染成白色或者黑色)。问最少操作次数。
输入格式
第一行两个数n,m表示矩形大小。
接下来n行描述目标状态,每行m个字符,’W’表示白色,’B’表示黑色。
接下来n行描述目标状态,每行m个字符,’W’表示白色,’B’表示黑色。
输出格式
一行一个整数表示操作数。
样例输入
3 3
WBW
BWB
WBW
WBW
BWB
WBW
样例输出
2
数据规模和约定
100%的数据n<=50,m<=50
15%的数据n*m<=15
另外15%的数据m=1
yy一下就可以知道……先把最外层染白,再把需要的染黑,然后染白染黑……就好了
所以设相邻的点互相通达,异色点距离为1,同色点距离为0,求每个点到黑点的最短距离中的最远距离,然后取最小的即为答案
#include <cstdio> #include <iostream> #include <cstring> using namespace std; const int vec[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; int ans,all,tot[2],n,m,i,j,k,dl[2][2501][2],maxn,o; int map[52][52],dis[52][52]; char s[52]; void dfs(int x,int y) { if (map[x][y]) maxn=max(maxn,dis[x][y]); for (int i=0;i<4;i++) { int X=x+vec[i][0],Y=y+vec[i][1]; if (1<=X && X<=n && 1<=Y && Y<=m) if (map[X][Y]^map[x][y]) if (dis[x][y]+1<dis[X][Y]) dis[X][Y]=dis[x][y]+1,dl[1-o][++tot[1-o]][0]=X,dl[1-o][tot[1-o]][1]=Y; else; else if (dis[x][y]<dis[X][Y]) dis[X][Y]=dis[x][y],dfs(X,Y); } } int check(int x,int y) { memset(dis,63,sizeof(dis)); maxn=0; tot[o]=1; dl[o][1][0]=x,dl[o][1][1]=y; dis[x][y]=0; while (tot[o]) { tot[1-o]=0; for (int i=1;i<=tot[o];i++) dfs(dl[o][i][0],dl[o][i][1]); o=1-o; } return maxn; } int main() { cin >> n >> m; for (i=1;i<=n;i++) { scanf("%s",s+1); for (j=1;j<=m;j++) if (s[j]=='W') all++; else map[i][j]=1; } if (all==n*m) { cout << 0; return 0; } ans=1<<30; for (i=1;i<=n;i++) for (j=1;j<=m;j++) ans=min(ans,check(i,j)); cout << ans+1; return 0; }