作者的正解:

对于100%的数据:行动可以分为两种:

1. 步行,花费一个单位的时间移动到4联通的相邻格子中去.

2. 使用传送门,指定一个方向的墙的前面的一个格子,步行至最近的一个墙的面前,使用传送门传送.花费的时间为到达最近墙面前花费的时间+1.

两种行动相组合即可组成任意行动过程.那BFS求出最近的墙的距离,预处理上下左右的第一面墙前的格子.然后建图用DJ跑最短路即可.复杂度为O(MNlog(NM))。

其实所的很清楚了,只是不知道bfs是个什么玩意……直接$n^3$暴扫就行了呀。倒真的没什么可说的,看代码吧。

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define MP(a,b) make_pair(a,b)
#define ma(x,y) memset(x,y,sizeof(x))
#define LL long long
#define INF 1000000
using namespace std;
struct edge
{
int u,v,w,nxt;
#define u(x) ed[x].u
#define v(x) ed[x].v
#define w(x) ed[x].w
#define n(x) ed[x].nxt
}ed[];
int first[],num_e;
#define f(x) first[x]
char map[][];
int up[][],un[][];
int le[][],re[][];
int n,m;
int cx,cy,fx,fy;
inline int get(int i,int j){return (i-)*m+j;}
inline pair<int,int> ret(int val){return MP(val/m+,val%m);}
int dis[];
bool v[];
void dist(int st)
{
ma(dis,0x7f);
priority_queue<pair<int,int> >q;
dis[st]=;q.push(MP(,st));
while(!q.empty())
{
int x=q.top().second;q.pop();
if(v[x])continue;v[x]=;
for(int i=f(x);i;i=n(i))
if(dis[x]+w(i)<dis[v(i)])
dis[v(i)]=dis[x]+w(i),
q.push(MP(-dis[v(i)],v(i)));
}
}
inline void add(int u,int v,int w);
signed main()
{
cin>>n>>m;
for(int i=;i<=n;i++)
scanf("%s",map[i]+);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
if(map[i][j]=='C')cx=i,cy=j;
if(map[i][j]=='F')fx=i,fy=j;
if(map[i][j]=='#')
up[i][j]=un[i][j]=le[i][j]=re[i][j]=INF;
else
{
for(int k=i-;k>;k--)//上
if(map[k][j]=='#'){up[i][j]=k+;break;}
for(int k=i+;k<=n;k++)//下
if(map[k][j]=='#'){un[i][j]=k-;break;}
for(int k=j-;k>;k--)//左
if(map[i][k]=='#'){le[i][j]=k+;break;}
for(int k=j+;k<=m;k++)//右
if(map[i][k]=='#'){re[i][j]=k-;break;}
}
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(map[i][j]!='#')
{
if(map[i-][j]!='#')add(get(i,j),get(i-,j),);//,add(get(i-1,j),get(i,j),1);//上
if(map[i+][j]!='#')add(get(i,j),get(i+,j),);//,add(get(i+1,j),get(i,j),1);//下
if(map[i][j-]!='#')add(get(i,j),get(i,j-),);//,add(get(i,j-1),get(i,j),1);//左
if(map[i][j+]!='#')add(get(i,j),get(i,j+),);//,add(get(i,j+1),get(i,j),1);//右
//上
{
add(get(i,j),get(un[i][j],j),i-up[i][j]+);//下
add(get(i,j),get(i,le[i][j]),i-up[i][j]+);//左
add(get(i,j),get(i,re[i][j]),i-up[i][j]+);//右
}
//下
{
add(get(i,j),get(up[i][j],j),un[i][j]-i+);//上
add(get(i,j),get(i,le[i][j]),un[i][j]-i+);//左
add(get(i,j),get(i,re[i][j]),un[i][j]-i+);//右
}
//左
{
add(get(i,j),get(up[i][j],j),j-le[i][j]+);//上
add(get(i,j),get(un[i][j],j),j-le[i][j]+);//下
add(get(i,j),get(i,re[i][j]),j-le[i][j]+);//右
}
//右
{
add(get(i,j),get(up[i][j],j),re[i][j]-j+);//上
add(get(i,j),get(un[i][j],j),re[i][j]-j+);//下
add(get(i,j),get(i,le[i][j]),re[i][j]-j+);//左
}
}
dist(get(cx,cy));
printf("%d\n",dis[get(fx,fy)]);
}
inline void add(int u,int v,int w)
{
if(u==v)return;
++num_e;
u(num_e)=u;
v(num_e)=v;
w(num_e)=w;
n(num_e)=f(u);
f(u)=num_e;
}

HZOJ 走格子的更多相关文章

  1. 51nod1486 大大走格子

    容斥定理+dp...妈呀#1rp耗尽了难怪最近那么衰... #include<cstdio> #include<cstring> #include<cctype> ...

  2. 1289 大鱼吃小鱼 1305 Pairwise Sum and Divide 1344 走格子 1347 旋转字符串 1381 硬币游戏

    1289 大鱼吃小鱼 有N条鱼每条鱼的位置及大小均不同,他们沿着X轴游动,有的向左,有的向右.游动的速度是一样的,两条鱼相遇大鱼会吃掉小鱼.从左到右给出每条鱼的大小和游动的方向(0表示向左,1表示向右 ...

  3. 51nod 1486 大大走格子(容斥原理)

    1486 大大走格子 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题   有一个h行w列的棋盘,里面有一些格子是不能走的,现在要 ...

  4. 51Nod 1344 走格子

    参考自:https://www.cnblogs.com/ECJTUACM-873284962/p/6445381.html 1344 走格子 基准时间限制:1 秒 空间限制:131072 KB 分值: ...

  5. 51Nod 1344 走格子(贪心

    1344 走格子   有编号1-n的n个格子,机器人从1号格子顺序向后走,一直走到n号格子,并需要从n号格子走出去.机器人有一个初始能量,每个格子对应一个整数A[i],表示这个格子的能量值.如果A[i ...

  6. 【51NOD】1486 大大走格子

    [算法]动态规划+组合数学 [题意]有一个h行w列的棋盘,定义一些格子为不能走的黑点,现在要求从左上角走到右下角的方案数. [题解] 大概能考虑到离散化黑点后,中间的空格子直接用组合数计算. 然后解决 ...

  7. 51nod 1344 走格子【贪心/前缀和】

    1344 走格子 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题  收藏  关注 有编号1-n的n个格子,机器人从1号格子顺序向后走,一直走到n号格子,并需要从n号格 ...

  8. 51Nod 1486 大大走格子 —— 组合数学

    题目链接:https://vjudge.net/problem/51Nod-1486 1486 大大走格子 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: ...

  9. 51nod1344 走格子

    1344 走格子 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题  收藏  关注 有编号1-n的n个格子,机器人从1号格子顺序向后走,一直走到n号格子,并需要从n号格 ...

随机推荐

  1. 关于springmvc 只能在index.jsp页面显示图片的处理办法jsp页面无法显示图片

    首先,已经配置好了mvc对静态资源的处理 只有index,jsp可以显示图片 其他页面同样的代码则不显示 后来折腾了半天,发现 index是static的父目录的级别文件 可以向下访问 但是其他的js ...

  2. case 和decode的区别

    区别: decode是pl/sql语法,只能在oracle中使用,case when是标准SQL的语法,哪儿都能用,也就是说移植性更强. decode像是case when的精简版,当要实现的功能比较 ...

  3. 系统日志和内核消息 $ dmesg$ less /var/log/messages$ less /var/log/secure$ less /var/log/auth

    查看错误和警告消息,比如看看是不是很多关于连接数过多导致? 看看是否有硬件错误或文件系统错误? 分析是否能将这些错误事件和前面发现的疑点进行时间上的比对.

  4. 门诊叫号系统系列-1.语音叫号 .net c#

    最近收到一个需求,朋友诊室需要做到门诊叫号,流程如下:病人选择医生-刷身份证排队-医生点击病人姓名叫号. 经过团队的努力,一个简易的门诊叫号系统已经完成.现在把各个功能记录下来,方便以后查看. 1.语 ...

  5. javascript最大公约数与最小公倍数

    var a = 5 ; var b = 15 ; var min = Math.min(a,b); var max = Math.max(a,b); // for循环求最大公约数 for(var i ...

  6. Js 克隆

    1.浅表克隆 调用concate() 或者slice() 方法,可以创建数组的浅表副本,在浅表副本中,如果原始数组的元素是复杂数据类型,则元素值指向对象的引用而非对象本身, 与原始数组一样,浅表副本的 ...

  7. js面向对象开发基础

    js的面向对象开发能力较弱,基本是以prototype为核心的面向对象,虽然现在出了个class这玩意,但本文还是先不做探讨. 面向对象基础——构造函数方法 var Fly = function (s ...

  8. PHP判断一个文件是否能够被打开

    <?php // 需求:因为系统涉及大量的文档知识库,用户可以在线进行查看.为了验证文档是否正常打开.先需要从数据库取出路径和文件名,判断是否可以从对应的路径下打开文件.header(" ...

  9. python第一天 :计算机基础(一)

    1.什么是编程语言 答:人类与计算机交流的介质 2.什么是编程 答:利用编程语言控制计算机解决问题 3.为什么要编程 答:可以控制计算机做事,提高生产生活效率 4.计算机的五大组成部分分别有什么作用? ...

  10. FZU 1575 小学生的游戏【模拟二分】

    某天,无聊的小斌叫上几个同学玩游戏,其中有比较笨的小兴,比较傻的小雪,可爱的小霞和自以为是的小楠.他们去找聪明的小明去给他们当裁判.判定谁取得游戏胜利. 而这个游戏是由小斌想个1到10000000的数 ...