P2124 奶牛美容
题目描述
输入输出格式
输入格式:
输出格式:
输入输出样例
6 16
................
..XXXX....XXX...
...XXXX....XX...
.XXXX......XXX..
........XXXXX...
..XXX....XXX....
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 奶牛美容的更多相关文章
- [洛谷P2124] 奶牛美容
洛谷题目链接:奶牛美容 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例#1: 6 16 ................ ..XXXX....XXX... ...XXXX... ...
- luogu P2124 奶牛美容
嘟嘟嘟 首先数据范围那么小,那么算法也是相当暴力的. 对于一个点(x, y)所属的联通块,预处理出从这个点出发到这个块外的所有点的曼哈顿距离.复杂度O(n4). 然后求答案:最少答案不一定是三个联通块 ...
- [LuoguP2124]奶牛美容_bfs_floyd_曼哈顿距离
奶牛美容 题目链接:https://www.luogu.org/problem/P2124 数据范围:略. 题解: 发现数据范围只有$50$,显然可以直接$bfs$求出联通块,$floyd$求出相邻两 ...
- poj 3614 奶牛美容问题 优先队列
题意:每头奶牛需要涂抹防晒霜,其中有效的范围 min~max ,现在有L种防晒霜,每种防晒霜的指数为 f 瓶数为 l,问多少只奶牛可以涂上合适的防晒霜?思路: 优先队列+贪心 当奶牛的 min< ...
- POJ 3614 Sunscreen (优先队列)
题意:奶牛美容:有C头奶牛日光浴,每头奶牛分别需要minSPF_i和maxSPF_i单位强度之间的阳光.现有L种防晒霜,分别能使阳光强度稳定为SPF_i,其瓶数为cover_i.求最多满足多少头奶牛 ...
- 【bzoj1708】[USACO2007 Oct]Money奶牛的硬币
题目描述 在创立了她们自己的政权之后,奶牛们决定推广新的货币系统.在强烈的叛逆心理的驱使下,她们准备使用奇怪的面值.在传统的货币系统中,硬币的面值通常是1,5,10,20或25,50,以及100单位的 ...
- 【bzoj1231】[Usaco2008 Nov]mixup2 混乱的奶牛
题目描述 混乱的奶牛[Don Piele, 2007]Farmer John的N(4 <= N <= 16)头奶牛中的每一头都有一个唯一的编号S_i (1 <= S_i <= ...
- 【BZOJ1623】 [Usaco2008 Open]Cow Cars 奶牛飞车 贪心
SB贪心,一开始还想着用二分,看了眼黄学长的blog,发现自己SB了... 最小道路=已选取的奶牛/道路总数. #include <iostream> #include <cstdi ...
- COGS130. [USACO Mar08] 游荡的奶牛[DP]
130. [USACO Mar08] 游荡的奶牛 ★☆ 输入文件:ctravel.in 输出文件:ctravel.out 简单对比时间限制:1 s 内存限制:128 MB 奶牛们在被划 ...
随机推荐
- ubuntu以root进入图形化界面
sudo nautilus 可以进行一些文件夹移动操作,不会出现权限的问题
- [转]Centos7 内核从3.10升级到4.12过程
[原文地址] http://blog.csdn.net/youshijifen/article/details/73472434 [摘要] 近期,国家互联网应急中心漏洞(CNCERT)公告中提到Lin ...
- JavaScript 转载
JavaScript概述 ECMAScript和JavaScript的关系 1996年11月,JavaScript的创造者--Netscape公司,决定将JavaScript提交给国际标准化组织ECM ...
- Python的jieba模块简介
现如今,词云技术遍地都是,分词模块除了jieba也有很多,主要介绍一下jieba的基本使用 import jieba import jieba.posseg as psg from os import ...
- 二维数组快速排序(sort+qsort)
二维数组快速排序 qsort是c中快速排序,如果简单的一维数组排序,想必大家的懂.现在看一下二维数组的排序,虽然可以冒泡但是太费时间了,我们这里使用qsort来快速排序,看代码应该看得懂吧. 代码: ...
- 链栈的c++实现
2013-08-30 20:58 1876人阅读 评论(0) 收藏 举报 链栈是借用单链表实现的栈.其不同于顺序栈之处在于: 1.链栈的空间是程序运行期间根据需要动态分配的,机器内存是它的上限.而顺序 ...
- node 动态页面渲染
代码: 'use strict' const express = require('express'); const consoldiate = require('consolidate'); con ...
- 【Leetcode】413. Arithmetic Slices
Description A sequence of number is called arithmetic if it consists of at least three elements and ...
- python学习之函数基础
第一个python函数: >>> def func_1(): ... print 'hello python' ... >>> func_1() hello pyt ...
- 图片验证码给AI使用
为了破解图形验证码,AI需要大量的图片数据.为了简单获取大量的图形来喂给Ai模型训练,索性自己写一把.代码来一发.. import java.awt.Color; import java.awt. ...