题解 洛谷P4872 【OIer们的东方梦】
一道码量比较大的套路广搜题……
首先看数据 \(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们的东方梦】的更多相关文章
- 洛谷 P5640 【CSGRound2】逐梦者的初心
洛谷 P5640 [CSGRound2]逐梦者的初心 洛谷传送门 题目背景 注意:本题时限修改至250ms,并且数据进行大幅度加强.本题强制开启O2优化,并且不再重测,请大家自己重新提交. 由于Y校的 ...
- 题解 洛谷P5018【对称二叉树】(noip2018T4)
\(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...
- 题解 洛谷 P3396 【哈希冲突】(根号分治)
根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...
- 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)
题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...
- 题解-洛谷P4229 某位歌姬的故事
题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...
- 题解-洛谷P4724 【模板】三维凸包
洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...
- 题解-洛谷P4859 已经没有什么好害怕的了
洛谷P4859 已经没有什么好害怕的了 给定 \(n\) 和 \(k\),\(n\) 个糖果能量 \(a_i\) 和 \(n\) 个药片能量 \(b_i\),每个 \(a_i\) 和 \(b_i\) ...
- 题解-洛谷P5217 贫穷
洛谷P5217 贫穷 给定长度为 \(n\) 的初始文本 \(s\),有 \(m\) 个如下操作: \(\texttt{I x c}\),在第 \(x\) 个字母后面插入一个 \(c\). \(\te ...
- 题解 洛谷 P2010 【回文日期】
By:Soroak 洛谷博客 知识点:模拟+暴力枚举 思路:题目中有提到闰年然后很多人就认为,闰年是需要判断的其实,含有2月29号的回文串,前四位是一个闰年那么我们就可以直接进行暴力枚举 一些小细节: ...
随机推荐
- socket支持ipv6
转自:https://www.jianshu.com/p/9926b99a7fef 以前cocos2d-x的项目里都使用的是libwebsocket,如果想支持ipv6,只需要升级相应的库即可,现在有 ...
- POJ1166 The Clocks (爆搜 || 高斯消元)
总时间限制: 1000ms,内存限制: 65536kB 描述 |-------| |-------| |-------| | | | | | | | |---O | |---O | | O | | | ...
- [JAVA] maven 阿里云节点 settings.xml
<?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://mav ...
- Create C/C++ DLLs in Visual Studio
https://docs.microsoft.com/zh-tw/cpp/build/dlls-in-visual-cpp?view=vs-2019 Walkthrough: Create and u ...
- mybatisGenerator
mybatisGenerator,可以自定义生成的xml,dao接口文件名称,可以自动在生成的实体类上添加数据库字段的注释 项目结构: 在generatorConfig.xml配置好数据库和对应的表, ...
- CF1051D Bicolorings
题目描述 咳咳,懒得复制了上面是两张图:) 解题思路 这题是一道很好的题,感觉之前做过,一开始手推状态找规律,可以用状压但是没想到 借鉴了一下大佬的dp modify数组用以累加新增的状态数 dp数组 ...
- quartz2.3.0(二)触发器Trigger花式Scheduler调度job
任务类 package org.quartz.examples.example2; import java.util.Date; import org.slf4j.Logger; import org ...
- Postman 基本使用
Postman 基本使用 Postman主界面 工具栏 New: 新建,可以新建Request请求,Collection请求集,环境等等 Import: 导入,可以导入别人导出的请求集 Runne ...
- 解决跟Docker私有仓库登陆,推送,拉取镜像出现的报错
出现问题:Error response from daemon: Get https://192.168.186.120/v1/users/: dial tcp 192.168.186.120:443 ...
- Hadoop 系列(六)—— HDFS 常用 Shell 命令
一.基本命令 打开 Hbase Shell: # hbase shell 1.1 获取帮助 # 获取帮助 help # 获取命令的详细信息 help 'status' 1.2 查看服务器状态 stat ...