P4554 小明的游戏 (洛谷) 双端队列BFS
最近没有更新博客,全是因为英语,英语太难了QWQ
洛谷春令营的作业我也不会(我是弱鸡),随机跳了2个题,难度不高,还是讲讲吧,学学新算法也好(可以拿来水博客)
第一题就是这个小明的游戏
小明最近喜欢玩一个游戏。给定一个 n×m的棋盘,上面有两种格子#和@。游戏的规则很简单:给定一个起始位置和一个目标位置,小明每一步能向上,下,左,右四个方向移动一格。如果移动到同一类型的格子,则费用是0,否则费用是1。请编程计算从起始位置移动到目标位置的最小花费。 输入格式 输入文件有多组数据。
输入第一行包含两个整数n,m,分别表示棋盘的行数和列数。
输入接下来的n行,每一行有m个格子(使用#或者@表示)。
输入接下来一行有四个整数x1, y1, x2, y2
分别为起始位置和目标位置。
当输入n,m均为0时,表示输入结束。 输出格式 对于每组数据,输出从起始位置到目标位置的最小花费。每一组数据独占一行。
看起来像个广搜,但是我们仔细想想的话会发现,这玩意是有权值的,可能我走100格用的费用比你走一格用的都少,在最少费用的要求下,显然不能用普通的广搜。
广搜的特点是把所有能走到的点全加进队列,为什么会用这种算法呢?,因为每走一步就需要一点费用的情况下,这样走花费最少。
于是,我们可以想出一个主意,我们让队列双开口,把花费小的放在前面,花费大的放后面岂不美哉。但有的同学可能会疑惑(其实只有我),这样的话不是要手打堆排?不不不,里面最多有2种数,因为我们去查看大数的情况前先要看小数的情况,小数只能变成自己或者自己+1,如果是自己+1,变成大数,放在最后。如果不是,放在前面再来一遍。所以这个队列里只会有2种数。不用担心排序的问题。
再来几个小提示就贴代码了:
1、队列记得清空
2、记得标记来过没
3、有个东西叫deque,deque支持高效插入和删除容器的头部和尾部元素,因此也叫做双端队列(我用的就是这个)
#include<iostream>
#include<cstdio>
#include<deque>
using namespace std;
char sz[505][505];
long long a[500][500];
long long n,m,qx,qy,zx,zy;
long long fx[4]={0,0,1,-1};//控制移动的数组
long long fy[4]={1,-1,0,0};
deque<int>qz;//3个双端队列
deque<int>xd;
deque<int>yd;
long long x,y,z;
void sddl()
{
while(xd.empty()!=true&&yd.empty()!=true)//不空不走
{
x=xd.front();//这个是获取队列的头部元素
y=yd.front();
z=qz.front();
if(x==zx&&y==zy)
{
while (xd.empty()!=true)xd.pop_front();//清空队列,我之前因为没清空疯狂80分
while (yd.empty()!=true)yd.pop_front();
while (qz.empty()!=true)qz.pop_front();
cout<<z<<endl;
return;
}
xd.pop_front();
yd.pop_front();
qz.pop_front();
for(int i=0;i<4;i++)
{
if(x+fx[i]>=0&&x+fx[i]<n&&y+fy[i]>=0&&y+fy[i]<m)//判断越界
{
if(a[x+fx[i]][y+fy[i]]==0)//标记来过没
{
a[x+fx[i]][y+fy[i]]=1;
if(sz[x+fx[i]][y+fy[i]]==sz[x][y])//走这个不需要花费,走起
{
xd.push_front(x+fx[i]);//这个是插入到头部的意思
yd.push_front(y+fy[i]);
qz.push_front(z);
}else//花费1点
{
xd.push_back(x+fx[i]);//这个是插入到尾部的意思
yd.push_back(y+fy[i]);
qz.push_back(z+1);
}
}
}
}
}
return;
}
int main()
{
while(true)
{
scanf("%lld%lld",&n,&m);
if(n==0&&m==0)
{
return 0;
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>sz[i][j];
a[i][j]=0;
}
}
scanf("%lld%lld%lld%lld",&qx,&qy,&zx,&zy);
a[qx][qy]=1;//省一下
xd.push_front(qx);//这个是插入到头部的意思
yd.push_front(qy);
qz.push_front(0);
sddl();
}
return 0;
}
阳光健康,就到这里吧。
P4554 小明的游戏 (洛谷) 双端队列BFS的更多相关文章
- CH 2601 - 电路维修 - [双端队列BFS]
题目链接:传送门 描述 Ha'nyu是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女Rika,从而被收留在地球上.Rika的家里有一辆飞行车.有一天飞行车的电路板突然出现了故障,导致 ...
- CH2601 电路维修(双端队列bfs)建图恶心
CH2601 电路维修 双端队列bfs,其实就是因为只有0和1所以可以直接2维护队列单调性(和优先队列一个道理) 建图的过程需要仔细斟酌(想一想id为什么这么写) 还有,空间要开够(很玄学),我一开始 ...
- Luogu P2243 电路维修 双端队列BFS
当转移的代价是0和一个分明不同的权值时,可以用双端队列BFS去跑(你跑最短路也没问题..QWQ) 而对于这道题,边旋转代价是1,不旋转代价是0:可以直接建图最短路,也可以跑BFS 这个题建图很有意思: ...
- codeforces 1064D 双端队列BFS
双端队列BFS解决的就是路径权值可能为0的图最短路问题,权值为0插入队头,否则插入队尾. 对于这个题,可以看作上下移动的路径的权值为0,左右移动权值为1,而且不能超过规定的步数. 直接广搜求覆盖的点的 ...
- 电路维修 (广搜变形-双端队列bfs)
# 2632. 「BalticOI 2011 Day1」打开灯泡 Switch the Lamp On [题目描述] 有一种正方形的电路元件,在它的两组相对顶点中,有一组会用导线连接起来,另一组则不会 ...
- 2601 电路维修 (双端队列bfs\优先队列bfs(最短路))
描述 Ha'nyu是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女Rika,从而被收留在地球上.Rika的家里有一辆飞行车.有一天飞行车的电路板突然出现了故障,导致无法启动. 电路板 ...
- POJ 3662 Telephone Lines【二分答案+最短路】||【双端队列BFS】
<题目链接> 题目大意: 在一个节点标号为1~n的无向图中,求出一条1~n的路径,使得路径上的第K+1条边的边权最小. 解题分析:直接考虑情况比较多,所以我们采用二分答案,先二分枚举第K+ ...
- HDU - 6386 Age of Moyu (双端队列+bfs)
题目链接 双端队列跑边,颜色相同的边之间的花费为0,放进队首:不同的花费为1,放进队尾. 用Dijkstra+常数优化也能过 #include<bits/stdc++.h> using n ...
- P4554 小明的游戏
SPFA板子题 #include <stdio.h> #include <string.h> #define Clean(X,K) memset(X,K,sizeof(X)) ...
随机推荐
- 使用vscode 开发go项目的最新姿势. go版本1.14.2
使用了go 1.14.2. 版本, 再也不用建src, pkg, bin 目录了, 以及再也不用强制配置GOPATH了 前提条件: 必须是 go mod 项目. 在工程目录下, 执行这样的命令生成 ...
- MFC exe文件生成的图标更改方法
MFC exe文件生成的图标更改方法 https://blog.csdn.net/txwtech/article/details/92980545
- JVM生命周期与运行过程
1. Java虚拟机的生命周期 Java虚拟机的生命周期 一个运行中的Java虚拟机有着一个清晰的任务:执行Java程序.程序开始执行时他才运行,程序结束时他就停止.你在同一台机器上运行三个程序,就会 ...
- 7、struct2的命名空间
采用命名空间可以区分不同action下面相同的函数名称 我们来看下面的一个程序的代码 我们来看下面的代码: 添加物料的action处理类: package com.weiyuan.test; publ ...
- TCP端口扫描类型-隐蔽扫描和僵尸扫描
TCP扫描有三种类型:全连接扫描,隐蔽扫描,僵尸扫描.全连接扫描无须赘述. 隐蔽扫描:发送完SYN数据包以及收到SYN/ACK数据包后不再发送SCK数据包,由于没有建立完整的TCP连接,所以在目标主机 ...
- Python 简明教程 --- 18,Python 面向对象
微信公众号:码农充电站pro 个人主页:https://codeshellme.github.io 代码能借用就借用. -- Tom Duff 目录 编程可分为面向过程编程和面向对象编程,它们是两种不 ...
- python+opencv实现图像缩放
x, y = img_.shape[0:2] img_ = cv2.resize(img_, (int(y/2), int(x/2))) 实现图像长宽缩小为原来的一半
- dart快速入门教程 (7.1)
7.面向对象 dart是一门使用类和单继承的面向对象语言,所有的对象都是类的实例,所有的类都是Object的子类,换句话说就是万物皆对象 7.1.类与对象 void main() { // 注意:ne ...
- 小师妹学JVM之:逃逸分析和TLAB
目录 简介 逃逸分析和栈上分配 TLAB简介 TLAB详解 设置TLAB空间的大小 TLAB中大对象的分配 TLAB空间中的浪费 总结 简介 逃逸分析我们在JDK14中JVM的性能优化一文中已经讲过了 ...
- pycharm远程连接vagrant虚拟机中mariadb数据库
1.虚拟机数据库设置--重启数据库 (1)vi /etc/my.cnf bind = 0.0.0.0 (2).远程不能用root用户连,得新建用户 select host,user from mysq ...