题解:CF37E Trial for Chief

题目分析

题意

给一张全白的图,每次可以将一个四联通块染黑或染白,求转化到目标最少染色次数。

分析

考虑倒着想,由目标染回原图。

易得倒着染回去和正着染的最少染色次数相同

所以我们考虑从最后的图入手。


考虑从某一个点 (i,j) 开始染色。

尝试进行建图。

在同样的颜色间转移的代价是 0

如果颜色不同,就需要至少进行一次染色,所以代价是 1

建图跑最短路即可。

每次跑完后用距离最大的点更新答案。(因为原图是白色,所以只统计黑点)

并且默认一开始需染一次色,所以 diss=1


发现边权只有 01

可以考虑使用 0-1 BFS 求最短路。(其实用 0-1BFS 求的话可以不用建图)

时间复杂度 O((nm)2)

Code

#include<bits/stdc++.h>
using namespace std;
#define maxn 52
string tmp;
int mp[maxn][maxn];
#define pos(i, j) (m*((i)-1)+j)
#define chk(i, j) ((i)&&(j)&&(i<=n)&&(j<=m))
vector<pair<int, int> > e[maxn*maxn];
deque<int> dq;
int dis[maxn*maxn];
int bfs(int x, int n, int m)
{
memset(dis, 0x3f, sizeof dis);
dis[x]=1;
dq.emplace_back(x);
while(!dq.empty())
{
auto u=dq.front();
dq.pop_front();
for(auto [v, w]:e[u])
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(w) dq.emplace_back(v);
else dq.emplace_front(v);
}
}
int ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(mp[i][j]) ans=max(ans, dis[pos(i, j)]);
return ans;
}
int main()
{
int n, m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>tmp;
for(int j=1;j<=m;j++)
mp[i][j]=(tmp[j-1]=='B');
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(chk(i-1, j)) e[pos(i, j)].emplace_back(pos(i-1, j), mp[i][j]!=mp[i-1][j]);
if(chk(i+1, j)) e[pos(i, j)].emplace_back(pos(i+1, j), mp[i][j]!=mp[i+1][j]);
if(chk(i, j-1)) e[pos(i, j)].emplace_back(pos(i, j-1), mp[i][j]!=mp[i][j-1]);
if(chk(i, j+1)) e[pos(i, j)].emplace_back(pos(i, j+1), mp[i][j]!=mp[i][j+1]);
}
int ans=numeric_limits<int>::max();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
ans=min(ans, bfs(pos(i, j), n, m));
cout<<ans;
}

本文作者:Jimmy-LEEE

本文链接:https://www.cnblogs.com/redacted-area/p/18379531

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Jimmy-LEEE  阅读(4)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起