为了反驳很对劲的太刀流,并不对劲的片手流决定与之针锋相对。

很对劲的太刀流->

2638: 黑白染色

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 177  Solved: 87
[Submit][Status][Discuss]

Description

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

Input

  第一行两个数n,m表示矩形大小。
  接下来n行描述目标状态,每行m个字符,’W’表示白色,’B’表示黑色。

Output

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

Sample Input

3 3
WBW
BWB
WBW

Sample Output

2

HINT

数据规模和约定
  100%的数据n<=50,m<=50
  15%的数据n*m<=15
  另外15%的数据m=1

——————————并不对劲的分界线——————

问:数据怎样?

答:极小!

问:极小的数据该怎么办?

答:网络流!神奇的dp!

然而并不是…有一个游戏(KAMI)是类似的,就是给出这样的一个有几种颜色的图:

每次可以选一个同色的区域,将这个区域染成另一种颜色。要在步数限制内将整个图染成同一种颜色。

有这样一种染色方法:

用三步将中间的部分染灰;

用一步将中间的部分染蓝;

用一步将中间的部分染灰;

用一步将中间的部分染蓝;

用一步将中间的部分染白,就完成了;

总共是3+1+1+1+1=7步,并不知道这是不是最优解。

这个游戏和这道题的区别在于有一个是把有图案的变成空白,另一个是把空白的变成有图案的。会发现这个游戏的操作正好是本题操作的逆变换。因为本游戏一开始是小的同色连通块,染色后是更大的同色连通块(必须是白色)。对于本题而言,如果把有不同颜色的连通块染成了同一颜色,就会让之前的某些操作白做了。这可能不会让总次数变多,但是绝对不可能让总次数变少,所以还是要尽量避免将不同色的染成同色的。那也就是说,这道题就是将大的白色联通块变成小的同色连通块,刚好相反。那么就可以直接将本题当成那个游戏的简化版(只有两种颜色),也就是将目标状态染成全白。

这个游戏的有一种策略就是选一个起点(不同的起点的结果当然不同了,所以要先在选起点上花一番心思),然后将起点所在的同色连通块染成它的边缘的颜色(因为只有两种颜色,所以并不用考虑边缘有多种颜色的情况)。不断重复直至所有点同色。有人可能觉得,将一些小的连通块不断合并次数会更少。考虑两点A,B,将“从黑走到白”或“从白走到黑”称为一步,A到B最少的步数为dis(A,B)。那么无论如何染色,A和B只能在至少dis(A,B)次后才能在同一个同色连通块。所以其实这两种策略的下界都一样, 但是第一种更容易考虑。

随便找一个点(黑白都行)作为起点,假设它的颜色为a,另一种颜色为b。每一次需要把起点所在的连通块染为b色,这样起点所在连通块边缘的那些颜色为b的点就都包含在连通块中了。再将起点所在的连通块染成a色,边缘的那些颜色为a的点就也包含再连通块中了。随便用bfs或者什么最短路算法就可以知道对于每个点,假如以该点为起点,那么一共需要多少步。最后再求个最小值。

还有一点,要是写最短路的话,总共有2500个点,floyd并不能过。但是会发现边数非常小,那么n遍dijkstra就行了。

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#define maxn 3020
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(isdigit(ch)==0 && ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline void write(int x)
{
int f=0;char ch[20];
if(!x){puts("0");return;}
if(x<0){putchar('-');x=-x;}
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
}
typedef struct node
{
int x,y;
bool operator <(const node &z)const
{
return(y>z.y);
}
}stnd;
priority_queue<stnd>q;
int dis[maxn],n,m,a,b,x[10]={1,0,-1,0},y[10]={0,1,0,-1},vis[maxn],maxt,ans=0x7fffffff;
char s[60][60];
int getn(int i,int j)
{
return (i-1)*m+j;
}
void getxy(int w,int &i,int &j)
{
j=w%m==0?m:w%m;
i=(w-j)/m+1;
}
void dij(int st)
{
memset(dis,-1,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[st]=0;
stnd tmp;tmp.x=st,tmp.y=0;
q.push(tmp);
while(!q.empty())
{
int u=q.top().x;q.pop();if(vis[u])continue;vis[u]=1;
for(int r=0;r<4;r++)
{
int i,j;getxy(u,i,j);
int k=i+x[r],l=j+y[r],v=getn(k,l),w=s[i][j]==s[k][l]?0:1;
//if(st==n*n)cout<<i<<" "<<j<<endl;
if(k<=0 || k>n || l<=0 || l>m)continue;
if(dis[v]>dis[u]+w || dis[v]==-1)
{
dis[v]=dis[u]+w;
if(!vis[v]){tmp.x=v,tmp.y=dis[v],q.push(tmp);}
}
}
}
maxt=0;
for(int i=1;i<=n*m;i++)
{
int xx,yy;getxy(i,xx,yy);
if(s[xx][yy]=='B')
{/*cout<<xx<<" "<<yy<<" "<<dis[i]<<endl;*/maxt=max(maxt,dis[i]);}
}//cout<<maxt<<"+++++++++++"<<endl;
ans=min(maxt,ans);
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
scanf("%s",s[i]+1);
for(int i=1;i<=n*m;i++)dij(i);
write(ans+1);
return 0;
}
/*
3 3
WBW
BWB
WBW
*/
/*
%%%Wang God orz
%%%Shing God orz
%%%Yangtze River God orz
%%%Bang God orz
%%%Cross God orz
%%%O God orz
%%%Destinies God orz
%%%Everyone Except Me
*/

  

不知道这一题会不会有多种颜色的强化版?如果有,假设共有k种颜色,那么能做到多少的数据范围?还是只能暴搜?

宣传一波电教,欢迎加入。

并不对劲的bzoj2638的更多相关文章

  1. 【Tsinsen A1039】【bzoj2638】黑白染色 (BFS树)

    Descroption 原题链接 你有一个\(n*m\)的矩形,一开始所有格子都是白色,然后给出一个目标状态的矩形,有的地方是白色,有的地方是黑色,你每次可以选择一个连通块(四连通块,且不要求颜色一样 ...

  2. 并不对劲的BJOI2019

    一些感想 现实并非游戏,并不支持反复刷关 猎人和防御工事一起被老山龙摧毁了: 猎人惨死雨中,结云村永无放晴之日: 猎人被狂龙病毒侵蚀,天空山上黑蚀龙泛滥. 好像这才是怪物猎人系列的真实结局呢 day ...

  3. 并不对劲的uoj276. [清华集训2016]汽水

    想要很对劲的讲解,请点击这里 题目大意 有一棵\(n\)(\(n\leq 50000\))个节点的树,有边权 求一条路径使该路径的边权平均值最接近给出的一个数\(k\) 输出边权平均值下取整的整数部分 ...

  4. 并不对劲的DFT

    FFT是一个很多人选择背诵全文的算法. #include<algorithm> #include<cmath> #include<complex> #include ...

  5. 并不对劲的字符串专题(三):Trie树

    据说这些并不对劲的内容是<信息学奥赛一本通提高篇>的配套练习. 并不会讲Trie树. 1.poj1056-> 模板题. 2.bzoj1212-> 设dp[i]表示T长度为i的前 ...

  6. 并不对劲的字符串专题(二):kmp

    据说这些并不对劲的内容是<信息学奥赛一本通提高篇>的配套练习. 先感叹一句<信息学奥赛一本通提高篇>上对kmp的解释和matrix67的博客相似度99%(还抄错了),莫非mat ...

  7. 并不对劲的bzoj1861: [Zjoi2006]Book 书架

    传送门-> 这题的正确做法是splay维护这摞书. 但是并不对劲的人选择了暴力(皮这一下很开心). #include<algorithm> #include<cmath> ...

  8. 并不对劲的bzoj3932: [CQOI2015]任务查询系统

    传送门-> 离线操作听上去很简单,遗憾的是它强制在线. 每个时刻可以看成可持久化线段树中的一个版本,而每一个版本的线段树维护的是值某一段区间且在这个版本对应的时刻出现的数之和. 会发现同一时刻可 ...

  9. 并不对劲的bzoj1853:[SCOI2010]幸运数字

    传送门-> 据说本题的正确读法是[shìng运数字]. 听上去本题很适合暴力,于是并不对劲的人就去写了.其实这题就是一个很普(有)通(趣)暴力+神奇的优化. 首先,会发现幸运数字很少,那么就先搜 ...

随机推荐

  1. [luoguP1027] Car的旅行路线(Floyd)

    传送门 建图麻烦,建完图搞一遍Floyd就好了. ——代码 #include <iostream> #include <cstdio> #include <cmath&g ...

  2. Iahub and Permutations(codeforces 314c)

    题意:给出一组排列,某些位置不知道(-1),要求求出有多少种还原方式,使得所有a[i]!=i /* 这是一道关于排列的动态规划,这种体大都可以当作棋盘来做,如果把i这个数放到第j个位置,那么就将棋盘的 ...

  3. 事件和委托: 第 6 页 .Net Framework中的委托与事件

    原文发布时间为:2008-11-01 -- 来源于本人的百度文章 [由搬家工具导入] .Net Framework中的委托与事件 尽管上面的范例很好地完成了我们想要完成的工作,但是我们不仅疑惑:为什么 ...

  4. APP后端处理视频的方案

    在当前的app应用中,到处都能看到视频的身影,例如,在社交类的app上,用户可以拍摄属于自己的小视频,并发布到相应得栏目,增加和好友们互动的机会. 后台常见的视频处理有以下几种: ·          ...

  5. [CERC2015]Digit Division

    题目描述 We are given a sequence of n decimal digits. The sequence needs to be partitioned into one or m ...

  6. 【Nginx】I/O多路转接之select、poll、epoll

    当需要读两个以上的I/O的时候,如果使用阻塞式的I/O,那么可能长时间的阻塞在一个描述符上面,另外的描述符虽然有数据但是不能读出来,这样实时性不能满足要求,大概的解决方案有以下几种: 1.使用多进程或 ...

  7. [PythonCode]扫描局域网的alive ip地址

    内网的主机都是自己主动分配ip地址,有时候须要查看下有那些ip在使用,就写了个简单的脚本. linux和windows下都能够用,用多线程来ping1-255全部的地址,效率不高.2分钟左右. 先凑合 ...

  8. Word 2013安裝字典

    不必從內建的字典中開始,Word 2013 可將您連結到 Office 市集,方便您挑選免費的字典,或從包括多語字典的字典集合中購買. 若要選擇並安裝您想要的字典,請以滑鼠右鍵按一下任何單字,並按一下 ...

  9. 磁盘显示为GPT(保护分区)

    问题描述:PE进入系统,在计算机管理里面磁盘显示为GPT(保护分区).此时硬盘是不能重新分区或者格式化的. 解决思路:低版本的WIndows(PE)是不支持GPT分区的,我们需要使用系统自带的Disk ...

  10. 《Spring设计思想》AOP设计基本原理

    0.前言 Spring 提供了AOP(Aspect Oriented Programming) 的支持, 那么,什么是AOP呢?本文将通过一个另外一个角度来诠释AOP的概念,帮助你更好地理解和使用Sp ...