最近没有更新博客,全是因为英语,英语太难了QWQ

洛谷春令营的作业我也不会(我是弱鸡),随机跳了2个题,难度不高,还是讲讲吧,学学新算法也好(可以拿来水博客)

第一题就是这个小明的游戏

  1. 小明最近喜欢玩一个游戏。给定一个 n×m的棋盘,上面有两种格子#和@。游戏的规则很简单:给定一个起始位置和一个目标位置,小明每一步能向上,下,左,右四个方向移动一格。如果移动到同一类型的格子,则费用是0,否则费用是1。请编程计算从起始位置移动到目标位置的最小花费。
  2.  
  3. 输入格式
  4.  
  5. 输入文件有多组数据。
  6. 输入第一行包含两个整数nm,分别表示棋盘的行数和列数。
  7. 输入接下来的n行,每一行有m个格子(使用#或者@表示)。
  8. 输入接下来一行有四个整数x1, y1, x2, y2
  9. 分别为起始位置和目标位置。
  10. 当输入nm均为0时,表示输入结束。
  11.  
  12. 输出格式
  13.  
  14. 对于每组数据,输出从起始位置到目标位置的最小花费。每一组数据独占一行。

看起来像个广搜,但是我们仔细想想的话会发现,这玩意是有权值的,可能我走100格用的费用比你走一格用的都少,在最少费用的要求下,显然不能用普通的广搜。

广搜的特点是把所有能走到的点全加进队列,为什么会用这种算法呢?,因为每走一步就需要一点费用的情况下,这样走花费最少。

于是,我们可以想出一个主意,我们让队列双开口,把花费小的放在前面,花费大的放后面岂不美哉。但有的同学可能会疑惑(其实只有我),这样的话不是要手打堆排?不不不,里面最多有2种数,因为我们去查看大数的情况前先要看小数的情况,小数只能变成自己或者自己+1,如果是自己+1,变成大数,放在最后。如果不是,放在前面再来一遍。所以这个队列里只会有2种数。不用担心排序的问题。

再来几个小提示就贴代码了:

1、队列记得清空

2、记得标记来过没

3、有个东西叫deque,deque支持高效插入和删除容器的头部和尾部元素,因此也叫做双端队列(我用的就是这个)

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<deque>
  4. using namespace std;
  5. char sz[505][505];
  6. long long a[500][500];
  7. long long n,m,qx,qy,zx,zy;
  8. long long fx[4]={0,0,1,-1};//控制移动的数组
  9. long long fy[4]={1,-1,0,0};
  10. deque<int>qz;//3个双端队列
  11. deque<int>xd;
  12. deque<int>yd;
  13. long long x,y,z;
  14. void sddl()
  15. {
  16. while(xd.empty()!=true&&yd.empty()!=true)//不空不走
  17. {
  18. x=xd.front();//这个是获取队列的头部元素
  19. y=yd.front();
  20. z=qz.front();
  21. if(x==zx&&y==zy)
  22. {
  23. while (xd.empty()!=true)xd.pop_front();//清空队列,我之前因为没清空疯狂80分
  24. while (yd.empty()!=true)yd.pop_front();
  25. while (qz.empty()!=true)qz.pop_front();
  26. cout<<z<<endl;
  27. return;
  28. }
  29. xd.pop_front();
  30. yd.pop_front();
  31. qz.pop_front();
  32. for(int i=0;i<4;i++)
  33. {
  34. if(x+fx[i]>=0&&x+fx[i]<n&&y+fy[i]>=0&&y+fy[i]<m)//判断越界
  35. {
  36. if(a[x+fx[i]][y+fy[i]]==0)//标记来过没
  37. {
  38. a[x+fx[i]][y+fy[i]]=1;
  39. if(sz[x+fx[i]][y+fy[i]]==sz[x][y])//走这个不需要花费,走起
  40. {
  41. xd.push_front(x+fx[i]);//这个是插入到头部的意思
  42. yd.push_front(y+fy[i]);
  43. qz.push_front(z);
  44. }else//花费1点
  45. {
  46. xd.push_back(x+fx[i]);//这个是插入到尾部的意思
  47. yd.push_back(y+fy[i]);
  48. qz.push_back(z+1);
  49. }
  50. }
  51. }
  52. }
  53. }
  54. return;
  55. }
  56. int main()
  57. {
  58. while(true)
  59. {
  60. scanf("%lld%lld",&n,&m);
  61. if(n==0&&m==0)
  62. {
  63. return 0;
  64. }
  65. for(int i=0;i<n;i++)
  66. {
  67. for(int j=0;j<m;j++)
  68. {
  69. cin>>sz[i][j];
  70. a[i][j]=0;
  71. }
  72. }
  73. scanf("%lld%lld%lld%lld",&qx,&qy,&zx,&zy);
  74. a[qx][qy]=1;//省一下
  75. xd.push_front(qx);//这个是插入到头部的意思
  76. yd.push_front(qy);
  77. qz.push_front(0);
  78. sddl();
  79. }
  80. return 0;
  81. }

阳光健康,就到这里吧。

P4554 小明的游戏 (洛谷) 双端队列BFS的更多相关文章

  1. CH 2601 - 电路维修 - [双端队列BFS]

    题目链接:传送门 描述 Ha'nyu是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女Rika,从而被收留在地球上.Rika的家里有一辆飞行车.有一天飞行车的电路板突然出现了故障,导致 ...

  2. CH2601 电路维修(双端队列bfs)建图恶心

    CH2601 电路维修 双端队列bfs,其实就是因为只有0和1所以可以直接2维护队列单调性(和优先队列一个道理) 建图的过程需要仔细斟酌(想一想id为什么这么写) 还有,空间要开够(很玄学),我一开始 ...

  3. Luogu P2243 电路维修 双端队列BFS

    当转移的代价是0和一个分明不同的权值时,可以用双端队列BFS去跑(你跑最短路也没问题..QWQ) 而对于这道题,边旋转代价是1,不旋转代价是0:可以直接建图最短路,也可以跑BFS 这个题建图很有意思: ...

  4. codeforces 1064D 双端队列BFS

    双端队列BFS解决的就是路径权值可能为0的图最短路问题,权值为0插入队头,否则插入队尾. 对于这个题,可以看作上下移动的路径的权值为0,左右移动权值为1,而且不能超过规定的步数. 直接广搜求覆盖的点的 ...

  5. 电路维修 (广搜变形-双端队列bfs)

    # 2632. 「BalticOI 2011 Day1」打开灯泡 Switch the Lamp On [题目描述] 有一种正方形的电路元件,在它的两组相对顶点中,有一组会用导线连接起来,另一组则不会 ...

  6. 2601 电路维修 (双端队列bfs\优先队列bfs(最短路))

    描述 Ha'nyu是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女Rika,从而被收留在地球上.Rika的家里有一辆飞行车.有一天飞行车的电路板突然出现了故障,导致无法启动. 电路板 ...

  7. POJ 3662 Telephone Lines【二分答案+最短路】||【双端队列BFS】

    <题目链接> 题目大意: 在一个节点标号为1~n的无向图中,求出一条1~n的路径,使得路径上的第K+1条边的边权最小. 解题分析:直接考虑情况比较多,所以我们采用二分答案,先二分枚举第K+ ...

  8. HDU - 6386 Age of Moyu (双端队列+bfs)

    题目链接 双端队列跑边,颜色相同的边之间的花费为0,放进队首:不同的花费为1,放进队尾. 用Dijkstra+常数优化也能过 #include<bits/stdc++.h> using n ...

  9. P4554 小明的游戏

    SPFA板子题 #include <stdio.h> #include <string.h> #define Clean(X,K) memset(X,K,sizeof(X)) ...

随机推荐

  1. C++核心编程

    C++核心编程 本阶段主要针对C++面向对象编程技术做详细讲解,探讨C++中的核心和精髓. 1 内存分区模型 C++程序在执行时,将内存大方向划分为4个区域 代码区:存放函数体的二进制代码,由操作系统 ...

  2. Python学习日志-02

    (2)Python如何运行程序 Python解释器简介: Python不仅仅是一门编程语言,它也是一个名为解释器的软件包.解释器是一种让其他程序运行起来的程序.当你编写了一段Python程序,Pyth ...

  3. ORA-12514:监听程序无法识别

    使用plsql远程登录oracle数据库时,出现无法识别监听程序的错误.很大机率是配置文件出错. 配置文件如下: listener.ora是服务器端用的,oracle监听程序,就是读的这个文件,里面有 ...

  4. 006.OpenShift持久性存储

    一 持久存储 1.1 持久存储概述 默认情况下,运行容器使用容器内的临时存储.Pods由一个或多个容器组成,这些容器一起部署,共享相同的存储和其他资源,可以在任何时候创建.启动.停止或销毁.使用临时存 ...

  5. 浅析Java中Ant的使用

     Ant是一种基于Java的打包工具,Ant脚本采用XML格式编写,默认的文件名为build.xml. Ant中常用的节点元素 Project Project是项目工程的顶级节点,一个build. ...

  6. JavaWeb网上图书商城完整项目--day02-26.查询所有分类功能之DAO层实现

    我们按照表示的设计 以及: package com.weiyuan.goods.category.domain; import java.util.List; public class Categor ...

  7. 删库吧,Bug浪——我们在同一家摸鱼的公司

    那些口口声声, Bug越来越难写人的,应该盯着你们: 像我一样,我盯着你们,满眼恨意. IT积攒了几十年的漏洞, 所有的死机.溢出.404和超时, 像是专门为你们准备的礼物. 圈复杂度.魔鬼变量.内存 ...

  8. vueX基础知识笔记

    接着昨天的知识点 mutations提交时,有时候达不到想要的响应式,我们必须要将数据提前放到state中,否则不会达到响应式的效果.比如 state.info['address'] = value ...

  9. 进度条的使用 Progress控件

    MFC编程实例二:进度条的使用 2011-03-22 09:09:09|  分类: C++(C语言) |  标签:进度  nlower  nupper  添加  mfc  |字号 订阅    本人用的 ...

  10. ORACLE数据库数据被修改或者删除恢复数据(闪回)

    1. SELECT * FROM CT_FIN_RiskItem  --先查询表,确定数据的确不对  (cfstatus 第一行缺少) 2. select * from CT_FIN_RiskItem ...