题目描述

输入输出格式

输入格式:

输出格式:

输入输出样例

输入样例#1:

6 16
................
..XXXX....XXX...
...XXXX....XX...
.XXXX......XXX..
........XXXXX...
..XXX....XXX....
输出样例#1:

4

Solution:

  本题一眼想到搜索(考试时打了半天,没调对~~手动滑稽~~)。事后讨论,发现神佬的思路有可行性也有一些错误,于是从中启发,再结合题解,便改出了类$floyd$的算法。

  首先,用一次$dfs$处理出$3$个连通块并标记,实现比较简单。

  再就是骚操作了,处理出每个$s[i][j]==X$的点所在连通块到其它所有点的最小曼哈顿距离$dis[k][i][j]$(表示第$k$个连通块到$[i,j]$点的最小曼哈顿距离)。

  然后对于每个是连通块上的点(即$s[i][j]==X$的点),去更新这个点所在连通块与其它连通块的最短距离($f[i][j]$表示第$i$个连通块与第$j$个连通块的最短距离),很显然的状态转移方程为:$f[p][q]=min(f[p][q],dis[q][i][j]),\;s[i][j]\in p$,(记得$f[p][q]=f[q][p]$)。

  然后就处理出了$3$个连通块两两之间的最短距离,则$ans$初值是$3$条边中$2$条搭配的最小值(因为要使$3$个连通块连通只要连$2$条边),至于为什么是初值赋值为这个最小值呢?

  那是因为可能存在两两连通块之间共用了点的情况,举个例子:

  $\begin{Bmatrix}
 X\;.\;.\;.\;X\\
 .\;\;.\;.\;.\;\;.\\
 .\;\;.\;.\;.\;\;. \\
 .\;.\;X\;.\;.
\end{Bmatrix}$

  此时求出的$3$个连通块之间的最小距离和为$9$则需要加的$X$个数为$9-2=7$(减$2$是很显然的道理,因为我们是以坐标算曼哈顿距离,两个点之间曼哈顿路径上的点数应该等于曼哈顿距离减$1$(有点类似于小学奥数的植树间隔问题),那么三个点之间实际上就是两个两个点之间的点数,显然是减$2$(怎么感觉自己说的有点绕,~手动滑稽,不信自己模拟~)),但这个例子的答案显然因该是$5$。

  很容易发现,上述情况属于三个连通块之间由非连通块上的点搭桥相连的情况(这不还是$floyd$嘛)。于是我们处理出初值$ans$后,还应该枚举中间点,计算三个点之间共用点搭桥的情况的最小值,更新$ans$。

  那么最后答案就是$ans-2$了。时间复杂度$O(n^3)$(这也只是最坏复杂度,基本体现在预处理枚举每个连通块到其它所有点的最小曼哈顿距离上了),但还是很轻易本题就$AC$了(貌似最优解!)。

  本题给我的启发就是:

  1、其实可以将连通块个数再增多,那么就是跑最小生成树处理初值$ans$,同理继续枚举中间点连接各连通块。

  2、其实$n\leq 50$的数据用此方法还是很水的,可以增大数据至少到$n\leq 200$。

代码:

#include<bits/stdc++.h>
#define il inline
#define ll long long
#define debug printf("%d %s\n",__LINE__,__FUNCTION__)
using namespace std;
int n,m,ans=,p[][],cnt,f[][],tot,dis[][][];
int dx[]={,-,,},dy[]={,,,-};
char s[][];
bool vis[][],lian[];
il void change(int x,int y,int c){
if(vis[x][y])return ;
if(s[x][y]=='X'){vis[x][y]=;p[x][y]=c;}
else return;
for(int i=;i<;i++){
int xx=dx[i]+x,yy=dy[i]+y;
change(xx,yy,c);
}
}
il void dfs(int kuai,int x,int y){
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
dis[kuai][i][j]=min(dis[kuai][i][j],abs(i-x)+abs(j-y));
}
int main()
{
cin>>n>>m;
for(int i=;i<=n;i++)scanf("%s",s[i]+);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(s[i][j]=='X'&&!vis[i][j])change(i,j,++cnt);
memset(dis,0x3f,sizeof(dis));
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(s[i][j]=='X')dfs(p[i][j],i,j);
memset(f,0x3f,sizeof(f));
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(s[i][j]=='X'){
f[p[i][j]][]=min(f[p[i][j]][],dis[][i][j]);
f[p[i][j]][]=min(f[p[i][j]][],dis[][i][j]);
f[p[i][j]][]=min(f[p[i][j]][],dis[][i][j]);
f[][p[i][j]]=f[p[i][j]][];
f[][p[i][j]]=f[p[i][j]][];
f[][p[i][j]]=f[p[i][j]][];
}
ans=min(f[][]+f[][],min(f[][]+f[][],f[][]+f[][]));
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
ans=min(ans,dis[][i][j]+dis[][i][j]+dis[][i][j]);
cout<<ans-;
return ;
}

P2124 奶牛美容的更多相关文章

  1. [洛谷P2124] 奶牛美容

    洛谷题目链接:奶牛美容 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例#1: 6 16 ................ ..XXXX....XXX... ...XXXX... ...

  2. luogu P2124 奶牛美容

    嘟嘟嘟 首先数据范围那么小,那么算法也是相当暴力的. 对于一个点(x, y)所属的联通块,预处理出从这个点出发到这个块外的所有点的曼哈顿距离.复杂度O(n4). 然后求答案:最少答案不一定是三个联通块 ...

  3. [LuoguP2124]奶牛美容_bfs_floyd_曼哈顿距离

    奶牛美容 题目链接:https://www.luogu.org/problem/P2124 数据范围:略. 题解: 发现数据范围只有$50$,显然可以直接$bfs$求出联通块,$floyd$求出相邻两 ...

  4. poj 3614 奶牛美容问题 优先队列

    题意:每头奶牛需要涂抹防晒霜,其中有效的范围 min~max ,现在有L种防晒霜,每种防晒霜的指数为 f 瓶数为 l,问多少只奶牛可以涂上合适的防晒霜?思路: 优先队列+贪心 当奶牛的 min< ...

  5. POJ 3614 Sunscreen (优先队列)

    题意:奶牛美容:有C头奶牛日光浴,每头奶牛分别需要minSPF_i和maxSPF_i单位强度之间的阳光.现有L种防晒霜,分别能使阳光强度稳定为SPF_i,其瓶数为cover_i.求最多满足多少头奶牛 ...

  6. 【bzoj1708】[USACO2007 Oct]Money奶牛的硬币

    题目描述 在创立了她们自己的政权之后,奶牛们决定推广新的货币系统.在强烈的叛逆心理的驱使下,她们准备使用奇怪的面值.在传统的货币系统中,硬币的面值通常是1,5,10,20或25,50,以及100单位的 ...

  7. 【bzoj1231】[Usaco2008 Nov]mixup2 混乱的奶牛

    题目描述 混乱的奶牛[Don Piele, 2007]Farmer John的N(4 <= N <= 16)头奶牛中的每一头都有一个唯一的编号S_i (1 <= S_i <= ...

  8. 【BZOJ1623】 [Usaco2008 Open]Cow Cars 奶牛飞车 贪心

    SB贪心,一开始还想着用二分,看了眼黄学长的blog,发现自己SB了... 最小道路=已选取的奶牛/道路总数. #include <iostream> #include <cstdi ...

  9. COGS130. [USACO Mar08] 游荡的奶牛[DP]

    130. [USACO Mar08] 游荡的奶牛 ★☆   输入文件:ctravel.in   输出文件:ctravel.out   简单对比时间限制:1 s   内存限制:128 MB 奶牛们在被划 ...

随机推荐

  1. 设置Vim编辑器里Tab的长度,行号

    使用Vim编辑器写脚本时,经常会遇到多重循环语句,习惯上会用tab键来补齐.这时设置tab键占用的长度,可以调节界面的松紧度,使其达到令人满意的效果. 在针对个别用户和所有用户来设置时,与编辑SSH相 ...

  2. vue 中父子组件之间的交互

    1,最直接的也是最简单的方法是利用props来数据传值. 子组件定义如下: props: { iconClass: { type: String, required: true }, classNam ...

  3. Python 2.6.6升级到Python2.7.15

    最近在使用Python处理MySQL数据库相关问题时,需要用到Python2.7.5及以上版本,而centos6.5等版本操作系统默认自带的版本为2.6.6,因此需要对python进行升级. Pyth ...

  4. Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO

    你有碰上过这样的提示吗? Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in t ...

  5. 什么是Session共享?请举出使用场景

    是指在一个浏览器对应多个Web服务时,服务端的Session数据需要共享.例如单点登录.Web服务器集群等场景都需要用到.多子服务. Session共享有多种解决方案,例如Tomcat插件,我最喜欢的 ...

  6. python--基本类型之列表

    Lest(列表): 定义和创建列表: 列表:是python以及其他语言中最常用的数据结构之一.python用 [] 来解析列表列表是可变的.--可以改变列表的内容可以用切片 a=['张三','李四', ...

  7. 【python3.X】python学习中排雷过程^_^

    问题一:python读取文件时报错:“UnicodeDecodeError: 'gbk' codec can't decode byte 0x8d in position 52: illegal mu ...

  8. thrift安装

    yum -y install gcc-c++ autoconf automake sysconftool boost boost-devel libtool perl-ExtUtils-MakeMak ...

  9. c#一些常用的方法集合

    是从一个asp.net mvc的项目里看到的.挺实用的. 通过身份证号码获取出生日期和性别 通过身份证号码获取出生日期和性别 #region 由身份证获得出生日期 public static stri ...

  10. Windows自带的磁盘填充命令

    一张不用了的SD卡要给别人,之前一直是手机使用的,担心有一些资料被恢复,想要将它内容清空.以前就知道数字公司有一个磁盘填充的工具,后来网上搜一搜发现Windows有一个自带的命令用于磁盘填充. 首先进 ...