您的位置:首页 > 其它

【TsinsenA1309】黑白染色题解

2015-08-04 11:21 393 查看

题面

试题来源

  2012中国国家集训队命题答辩

问题描述

  你有一个n*m的矩形,一开始所有格子都是白色,然后给出一个目标状态的矩形,有的地方是白色,有的地方是黑色,你每次可以选择一个连通块(四连通块,且不要求颜色一样)进行染色操作(染成白色或者黑色)。问最少操作次数。

输入格式

  第一行两个数n,m表示矩形大小。

  接下来n行描述目标状态,每行m个字符,’W’表示白色,’B’表示黑色。

输出格式

  一行一个整数表示操作数。

样例输入

3 3

WBW

BWB

WBW

样例输出

2

数据规模和约定

  100%的数据n<=50,m<=50

  15%的数据n*m<=15

  另外15%的数据m=1

题解

分析

设相邻的点互相通达,异色点距离为1,同色点距离为0

首先应知道,异色两点距离为奇数,同色两点距离为偶数

(请自行证明)

那么设某个点到每个黑点的最短距离中的最远距离为d

我们有一种最优染色方案(请自行证明最优性)

Step 1:将距离为d以内的点染为黑色

Step 2:将距离为d-1以内的点染为白色

Step 3:将距离为d-2以内的点染为黑色

·

·

·

Step d:将距离为1以内的点染为相应颜色

Step d+1:将距离为0的点(即自己所在区域)染为相应颜色

所以我们只要找到最小的d

输出dmin+1d_{min}+1即可

代码

#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;
}


听你说这是道图论题???
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: