一道码量比较大的套路广搜题……

首先看数据 \(n,m \leq 1000\) 不是特别恶心,不难想到广搜。

由于这道题每走一步的代价不是 \(1\),所以并不能保证每次搜到的点就是最优解。那么可以考虑用一个数组 \(h[i][j][sun][kill]\) 来维护一下。

其中的 \({i,j,sun,kill}\) 是记录一个状态,表示在走到点 \((i,j)\) 时是否有太阳花田和楼关剑。而 \(h[i][j][sun][kill]\) 则表示到达这个状态下的最短路径。

这样就可以有效的剪枝了,因为有了最短路数组的维护我们可以排除到达当前状态没有最短路优的路径。而如果比最短路优,那么最短路就更新为当前路径,效率将有所提高。

期望得分:\(80-90\)

接下来考虑用优先队列优化。

可以这样想,我们把所有广搜的状态存入优先队列,每次弹出当前最短的状态,可以证明其扩展到的点一定也是最短的(因为没有负环)。

于是重载一下小于号运算符就行了,搜到终点就一定是最短路,然后把状态 \((i,j,sun,kill)\) 打上标记即可。其实和 \(\operatorname{dijkstra}\) 方法类似。

时间复杂度 \(O(4nm\) \(log\) \(4nm)\)

\(\operatorname{Coding}\) 时注意两点:

  • 传送门前后都要判一下标记

  • 楼观剑可以经过而不取

#include<bits/stdc++.h>
using namespace std;
const int max_n=1000+5;
int a[max_n][max_n];
bool h[max_n][max_n][2][2];//标记状态
struct node{
int x,y,f,sun,kill;
bool operator<(const node&a)const{//重载小于运算符
return f>a.f;
}
};
priority_queue<node>q;
vector< pair<int,int> >s;//传送门
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//上下左右
int main(){
ios::sync_with_stdio(false);
int n,m;cin>>n>>m;
int fx,fy,lx,ly;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
char ch;cin>>ch;
if(ch=='S')fx=i,fy=j;
if(ch=='E')lx=i,ly=j;
if(isdigit(ch))a[i][j]=ch-'0';
if(ch=='X')a[i][j]=6,s.push_back(make_pair(i,j));
}
}
h[fx][fy][0][0]=1;
q.push({fx,fy,0,0,0});
while(!q.empty()){
int x=q.top().x,y=q.top().y,f=q.top().f;
int sun=q.top().sun,kill=q.top().kill;
if(x==lx&&y==ly){//到终点一定是最优解
cout<<f<<"\n";
return 0;
}
for(int i=0;i<4;i++){
int tx=x+dir[i][0],ty=y+dir[i][1];
if(!(tx>=1&&tx<=n&&ty>=1&&ty<=m))continue;//不能超边界
if(a[tx][ty]==6){//传送门
if(h[tx][ty][sun][kill])continue;//这里不写84分AC再见
for(int j=0;j<s.size();j++){//枚举下一个传送门
int ttx=s[j].first,tty=s[j].second;
if(tx==ttx&&ty==tty)continue;//传送门当然不能自己传给自己哦
if(h[ttx][tty][sun][kill])continue;
h[ttx][tty][sun][kill]=1;//标记
q.push({ttx,tty,f+2,sun,kill});//入队
}
}
if(a[tx][ty]==0){//普通的点
if(h[tx][ty][sun][kill])continue;
h[tx][ty][sun][kill]=1;
q.push({tx,ty,f+1,sun,kill});
}
if(a[tx][ty]==1&&kill){//这里是墙,要经过必须要有楼观剑
if(h[tx][ty][sun][kill])continue;
h[tx][ty][sun][kill]=1;
q.push({tx,ty,f+1,sun,kill});
}
if(a[tx][ty]==2){//小怪兽
if(h[tx][ty][sun][kill])continue;
h[tx][ty][sun][kill]=1;
if(kill||sun)q.push({tx,ty,f+1,sun,kill});//如果有楼观剑或太阳花就可以直接上去
else q.push({tx,ty,f+4,sun,kill});//否则要花时间把它打死
}
if(a[tx][ty]==3){//大怪兽(和小怪兽同理)
if(h[tx][ty][sun][kill])continue;
h[tx][ty][sun][kill]=1;
if(kill||sun)q.push({tx,ty,f+1,sun,kill});
else q.push({tx,ty,f+9,sun,kill});
}
if(a[tx][ty]==4){//太阳花,只要经过就能得到
if(h[tx][ty][1][kill])continue;
h[tx][ty][1][kill]=1;
q.push({tx,ty,f+1,1,kill});
}
if(a[tx][ty]==5){//楼观剑
if(h[tx][ty][sun][1]==0){//取
h[tx][ty][sun][1]=1;
q.push({tx,ty,f+6,sun,1});
}
if(h[tx][ty][sun][kill]==0){//不取
h[tx][ty][sun][kill]=1;
q.push({tx,ty,f+1,sun,kill});
}
}
}
q.pop();
}
cout<<"We want to live in the TouHou World forever\n";
return 0;
}

\(\operatorname{Update}\) \(\operatorname{On}\) \(\operatorname{2019.08.26}\)

题解 洛谷P4872 【OIer们的东方梦】的更多相关文章

  1. 洛谷 P5640 【CSGRound2】逐梦者的初心

    洛谷 P5640 [CSGRound2]逐梦者的初心 洛谷传送门 题目背景 注意:本题时限修改至250ms,并且数据进行大幅度加强.本题强制开启O2优化,并且不再重测,请大家自己重新提交. 由于Y校的 ...

  2. 题解 洛谷P5018【对称二叉树】(noip2018T4)

    \(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...

  3. 题解 洛谷 P3396 【哈希冲突】(根号分治)

    根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...

  4. 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)

    题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...

  5. 题解-洛谷P4229 某位歌姬的故事

    题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...

  6. 题解-洛谷P4724 【模板】三维凸包

    洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...

  7. 题解-洛谷P4859 已经没有什么好害怕的了

    洛谷P4859 已经没有什么好害怕的了 给定 \(n\) 和 \(k\),\(n\) 个糖果能量 \(a_i\) 和 \(n\) 个药片能量 \(b_i\),每个 \(a_i\) 和 \(b_i\) ...

  8. 题解-洛谷P5217 贫穷

    洛谷P5217 贫穷 给定长度为 \(n\) 的初始文本 \(s\),有 \(m\) 个如下操作: \(\texttt{I x c}\),在第 \(x\) 个字母后面插入一个 \(c\). \(\te ...

  9. 题解 洛谷 P2010 【回文日期】

    By:Soroak 洛谷博客 知识点:模拟+暴力枚举 思路:题目中有提到闰年然后很多人就认为,闰年是需要判断的其实,含有2月29号的回文串,前四位是一个闰年那么我们就可以直接进行暴力枚举 一些小细节: ...

随机推荐

  1. NOI2019 Fe

    NFLS XY NOI2019 Fe Orz zsy,zhf,wqy,zjc,bly! Goodbye OI!

  2. spring security的BCryptPasswordEncoder加密和对密码验证的原理

    目录 BCryptPasswordEncoder加密和对密码验证的原理 一.加密算法和hash算法的区别 二.源码解析 1. encode方法 2. BCrypt.hashpw方法 3. matche ...

  3. LeetCode 611. 有效三角形的个数(Valid Triangle Number)

    611. 有效三角形的个数 611. Valid Triangle Number 题目描述 LeetCode LeetCode LeetCode611. Valid Triangle Number中等 ...

  4. lambda表达式已经成为了开发者必须要掌握的技能?

    lambda表达式 lambda表达式是什么 引用百度百科 “Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的la ...

  5. python中将已有链接的视频进行下载

    使用python爬取视频网站时,会得到一系列的视频链接,比如MP4文件.得到视频文件之后需要对视频进行下载,本文写出下载视频文件的函数. 首先导入requests库,安装库使用pip install ...

  6. tft_LCD一些引脚极性设置方法:vsync, hsync, VBLANK

    转载:https://blog.csdn.net/u014170207/article/details/52662988/ 在RGB模式中,LCD数据的扫描是以行为单位的.HSYNC是水平同步信号.P ...

  7. TextField 、 FTE、 TLF 的使用情景和简单说明

    作者:tiangej 来源:CSDN 原文:https://blog.csdn.net/tiangej/article/details/16859239 版权声明:本文为博主原创文章,转载请附上博文链 ...

  8. DataGrip License server

    之前用 Resharper 使用 http://xidea.online 来激活 今天下载一个DataGrip 发现不能使用这个地址,不知道是被封杀了还是不能跟 Resharper 的共用 在网上找到 ...

  9. 分享-SpringCloud微服务架构图

    1: 为大家分享一张SpringCloud微服务通用架构图 ​标题 此图仅供参考: 需要原图的同学请移步 >>>>>>>>> 这里 如有不合理的地 ...

  10. php后台实现页面跳转的方法-转载

    地址:http://blog.csdn.net/abandonship/article/details/6459104 其中方法三的js代码在tp框架使用存在故障,一个是需要把代码写在一起(可能也不需 ...