当前位置:   article > 正文

2.8数据结构与算法学习日记(bfs和01背包和完全背包)

2.8数据结构与算法学习日记(bfs和01背包和完全背包)

P8673 [蓝桥杯 2018 国 C] 迷宫与陷阱

题目描述

小明在玩一款迷宫游戏,在游戏中他要控制自己的角色离开一间由 N×N 个格子组成的二维迷宫。

小明的起始位置在左上角,他需要到达右下角的格子才能离开迷宫。

每一步,他可以移动到上下左右相邻的格子中(前提是目标格子可以经过)。

迷宫中有些格子小明可以经过,我们用 . 表示;

有些格子是墙壁,小明不能经过,我们用 # 表示。

此外,有些格子上有陷阱,我们用 X 表示。除非小明处于无敌状态,否则不能经过。

有些格子上有无敌道具,我们用 % 表示。

当小明第一次到达该格子时,自动获得无敌状态,无敌状态会持续 K 步。

之后如果再次到达该格子不会获得无敌状态了。

处于无敌状态时,可以经过有陷阱的格子,但是不会拆除 / 毁坏陷阱,即陷阱仍会阻止没有无敌状态的角色经过。

给定迷宫,请你计算小明最少经过几步可以离开迷宫。

输入格式

第一行包含两个整数 N 和 K。(1≤N≤1000,1≤K≤10)。

以下 N 行包含一个 N×N 的矩阵。

矩阵保证左上角和右下角是 .

输出格式

一个整数表示答案。如果小明不能离开迷宫,输出 −1−1。

输入输出样例

输入 #1复制

5 3
...XX
##%#.
...#.
.###.
.....

输出 #1复制

10

输入 #2复制

5 1
...XX
##%#.
...#.
.###.
.....

输出 #2复制

12

说明/提示

时限 3 秒, 256M。蓝桥杯 2018 年第九届国赛

题目分析

1,题目需考虑无敌状态以及无敌道具,所以我们需要在bfs时把这些条件加进去考虑,定义一个标记数组用来表是否走过和当前无敌所剩时间

2.在结构体内新加一个变量 magic,表示当前还剩几步的无敌状态。在遍历过程中,如果遇到“X”,并且不剩无敌了,就不能走;如果遇到“%”,magic 会重置成k。其他情况,并且不为“#”时,该点入队。

3,再进行剪枝操作符合能走的条件(book[nx][ny]<magic的作用是把肯定不是最优的情况排除,就是当前我走这个点剩下的无敌步数要大于之前剩下的,这会更优,所以可以走)

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N=1e3+5;
  4. int n,k;
  5. char a[N][N];
  6. int book[N][N];
  7. struct node
  8. {
  9. int x,y,step,magic;
  10. };
  11. int dx[4]= {1,-1,0,0};//方向数组
  12. int dy[4]= {0,0,1,-1};
  13. int bfs()
  14. {
  15. queue<node>p;
  16. book[1][1]=0;
  17. p.push({1,1,0,0});
  18. while(p.size())
  19. {
  20. node t=p.front();//查看队列头
  21. p.pop();
  22. if(t.x==n&&t.y==n)
  23. {
  24. cout<<t.step;
  25. return 0;//到达终点所以输出步数然后返回
  26. }
  27. for(int i=0; i<4; i++)
  28. {
  29. int nx=t.x+dx[i];
  30. int ny=t.y+dy[i];
  31. if(a[nx][ny]=='X'&&t.magic==0)//没有无敌又有陷阱,所以不能走
  32. continue;
  33. int magic=max(0,t.magic-1);//查看现在的无敌剩下步数
  34. if(a[nx][ny]=='%')magic=k;
  35. if(nx>=1&&nx<=n&&ny>=1&&ny<=n&&book[nx][ny]<magic&&a[nx][ny]!='#')//符合能走的条件(book[nx][ny]<magic的作用是把肯定不是最优的情况排除,就是当前我走这个点剩下的无敌步数要大于之前剩下的,这会更优,所以可以走)
  36. {
  37. book[nx][ny]=magic;
  38. p.push({nx,ny,t.step+1,magic});//入队更新步数和无敌状态
  39. }
  40. }
  41. }
  42. cout<<-1;
  43. return 0;
  44. }
  45. int main(){
  46. cin>>n>>k;
  47. for(int i=1;i<=n;i++)
  48. for(int j=1;j<=n;j++)
  49. cin>>a[i][j];
  50. memset(book,-1,sizeof(book));//初始化为-1
  51. bfs();
  52. }

P1115 最大子段和

题目描述

给出一个长度为 n 的序列 a,选出其中连续且非空的一段使得这段和最大。

输入格式

第一行是一个整数,表示序列的长度 n。

第二行有 n 个整数,第 i 个整数表示序列的第 i 个数字 ai​。

输出格式

输出一行一个整数表示答案。

输入输出样例

输入 #1复制

7
2 -4 3 -1 2 -4 3

输出 #1复制

4

说明/提示

样例 1 解释

选取 [3,5][3,5] 子段 {3,−1,2}{3,−1,2},其和为 44。

数据规模与约定
  • 对于 40%40% 的数据,保证 n≤2×103。
  • 对于 100%100% 的数据,保证 1≤n≤2×105,−104≤ai​≤104。

题目分析 

1,既然是求最大的子段和,所以我们要找出每个子段的和并边找边比大小,所以有个max变量一直在存放最大值

2,记录子段和,b[i]记录到i时,i之前的所有子段和

3,对于一直往后加,我们可以这样考虑(取与不取)取的条件是要求取他后总和会比之前的大,不然取着没意义,不取是加上后还比之前的小,那么就到这吧,不取了,下一个子段的开头以他为首赋值给b[i];

代码示例

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int b[200020],a[200020],i,n,ans=-9999;//因为要取最大值,所以从最小的开始找
  4. int main(){
  5. cin>>n;
  6. for(i=1;i<=n;i++)
  7. {cin>>a[i];
  8. if(n==1)b[i]=a[i];
  9. else b[i]=max(a[i],b[i-1]+a[i]);//判断取不取,哪个更优
  10. ans=max(ans,b[i]);//最大值
  11. }
  12. cout<<ans;
  13. }

 p1616疯狂的采药

题目背景

此题为纪念 LiYuxiang 而生。

题目描述

LiYuxiang 是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同种类的草药,采每一种都需要一些时间,每一种也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”

如果你是 LiYuxiang,你能完成这个任务吗?

此题和原题的不同点:

1. 每种草药可以无限制地疯狂采摘。

2. 药的种类眼花缭乱,采药时间好长好长啊!师傅等得菊花都谢了!

输入格式

输入第一行有两个整数,分别代表总共能够用来采药的时间 t 和代表山洞里的草药的数目 m。

第 2 到第 (m+1) 行,每行两个整数,第 (i+1) 行的整数 ai​,bi​ 分别表示采摘第 i 种草药的时间和该草药的价值。

输出格式

输出一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。

输入输出样例

输入 #1复制

70 3
71 100
69 1
1 2

输出 #1复制

140

说明/提示

数据规模与约定
  • 对于 30%30% 的数据,保证 m≤103 。
  • 对于 100%100% 的数据,保证 1≤m≤104,1≤t≤107,且 1≤m×t≤107,1≤ai​,bi​≤104

 题目分析

1,和之前的采药http://t.csdnimg.cn/SFpwD不同的是,他是可以重复采摘,所以在这里就变成了完全背包问题

2,此时给他数组压缩成一维数组得到dp[j]=max(dp[i],dp[j-w[i]]+v[i])

3.j表截止到j时的最大容量,dp[j]表截止到j容量的价值

代码示例

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int maxm=10010,maxt=10000010;
  4. long long v[maxm],t[maxt],dp[maxt];
  5. int main(){
  6. int T,m;
  7. cin>>T>>m;
  8. for(int i=1;i<=m;i++)
  9. cin>>t[i]>>v[i];
  10. for(int i=1;i<=m;i++)
  11. for(int j=t[i];j<=T;j++)//完全背包一维数组用从前往后遍历(这样会保证重复取),01背包一维数组从后往前遍历
  12. dp[j]=max(dp[j],dp[j-t[i]]+v[i]);//判断是否取,然后j表截止到j的最大容量,dp[j]表截止到j容量的价值
  13. cout<<dp[T];
  14. }


    

           

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/article/detail/77724
推荐阅读
  • 简单不先于复杂,而是在复杂之后。【数据结构]排序算法插入排序希尔排序选择排序简单不先于复杂,而是在复杂之后。文章目录1.排序的概念及其运用1.1排序的概念1.2排序运用1.3常见的排序算法2.常见排序算法的实现2.1插入排序2.1.1... [详细]

  • n个人围成一圈,从某人开始报数1,2,…,m,数到m的人出圈,然后从出圈的下一个人(m+1)开始重复此过程,如当n=8,m=4时,若从第一个位置数起,则所得到的新的序列为4,8,5,2,1,3,7,6。一、请编程实现单向循环链表的头插,头删... [详细]

  • C++实现图,置、复、查询。【数据结构10图一、图在海量数据的标记的时候,比如数十亿上百亿上千亿的数据,我们要统计数据是否出现,直接存储数据的话对内存的消耗太大了,这时我们可以通过图来标记出现过的数据,图可以标记0~42亿之... [详细]

  • 线性表(linearlist)是n个具有相同特性的数据元素的有限序列。线性表在,也就说是连续的一条直线。但是,线性表在物理上存储时,通常以数组和链式结构的形式存储。数据结构——顺序表1.线性表线性表(linearlist)是n个具有相同特性... [详细]

  • LeetCode经典数据结构与算法)题刷题指南:哈希篇_力扣哈希经典例题力扣哈希经典例题哈希更多请查看我的专栏:LeetCode力扣)刷题指南可直接在LeetCode中搜索题目名称文章目录哈希1.两数之和1.1解决方案1.暴力法(... [详细]

  • 主要讲解单向链表的几种接口实现原理及代码演示【数据结构单向链表实现超详细目录一.单链表实现1.准备工作及其注意事项1.1先创建三个文件1.2注意事项:帮助高效记忆和理解2.链表的基本功能接口2.0创建一个链表2.1链表的打印 ... [详细]

  • 散列表(Hashtable,也叫哈希表),是根据键(Key)而直接访问在内存储存位置的数据结构。也就是说,它通过计算出一个键值的函数,将所需查询的数据映射到表中一个位置来让人访问,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称... [详细]

  • 加线将p结点是双亲结点左孩子,则将p右孩子,右孩子右孩子…沿分支找到所有右孩子,都与p双亲用线连起来。抹线二叉中根结点与其右孩子连线,及沿右分支搜索到所有右孩子间连线全部抹掉,使之变成孤立二叉。以第一棵根结点为二叉... [详细]

  • 1:.size()是容器或者字符串使用的2:数组初始化方式//所有元素初始化为0必须指定大小3:时间复杂度为3次O(n)->O(n)4:本题使用数组构建哈希是因为数据大小已知了,若未知要用其他的数据结构时间复杂度:O(mn)空间复杂度:O... [详细]

  • tips:长方格中的left、right,分别代表该节点所求得的区间和。例如,left:0,right:4。代表nums中索引0到4的和=2+5+1+4+3=15。逻辑其实和建树一样,在线段树中找到修改节点的对应索引,然后修改其值,然后再依... [详细]

  • 基础数据结构--顺序数据结构顺序】文章目录线性顺序1.1顺序结构的定义1.2初始化顺序1.3检查顺序空间1.4打印1.5尾插1.6头插1.7尾删1.8头删1.9查找1.10指定位置插入1.11删除指定位置数据1.12销毁顺... [详细]

  • 我们实现的是一个带头结点的循环,具体方法是设置两个工作指针p、q。p从第一个节点开始从头到尾进行遍历,而q从最后一个结点开始从未到头依次遍历。两个指针同时移动,每移动一次就进行一次数据元素的交换。核心代码如下:voidd()//循环双... [详细]

  • 将两个递增的有序链表合并为一个递增的有序链表。要求结果链表仍使用原来两个链表的存储空间,不另外占用其它的存储空间_合并链表合并链表数据结构算法题将两个递增的有序链表合并为一个递增的有序链表。要求结果链表仍使用原来两个链表的存储空间,不另外占... [详细]

  • 数据结构两个递增序列合并为一个递增有序链表(要求:不占用多余存储空间,新链中不允许有重复元素)求解思路假设两个需要和合并链表为La和Lb,合并头指针用Lc来代替。设置pa,pb分别为La,Lb工作指针,pc用来保证新链完整性... [详细]

  • 链表力扣面试题系列⑤_合并两个有序链表合并两个有序链表目录方法一:无头结点的方法 方法二:有头结点的方法题述:已给函数头:structListNode*mergeTwoLists(structListNode*l1,structL... [详细]

  • 数据结构分为逻辑结构和物理结构,从逻辑结构上,数据结构分为集合结构数据元素之间没有关系、线性结构数据元素之间存在一对一的关系、树形结构数据元素之间存储一对多的关旭形结构数据元素之间存在多对多的关系;在很多情况下,我们需要... [详细]

  • ai,j在第i行,由上图可知,第i行有i个元素;ai,j在第j列,也可以理解为在第i行的弟j个位置。i,j**元素的前面一共有的元素个数为:[1+2+…+(i-1)]+j**按照行优先的原则,确定ai,j是一维数组中B[k]中的第几个元素。... [详细]

  • 数据结构链表数据结构-双向链表1.容器容器用于容纳元素集合,并对元素集合进行管理和维护.传统意义上的管理和维护就是:增,删,改,查.我们分析每种类型容器时,主要分析其增,删,改,查动作实现,及复杂度.2.双向链表2.1.结构2.1.1.图... [详细]

  • 前言单链表中同样也有具有挑战性的题目,链表带环问题可以说是众多难题中的佼佼者,在这里可能更看重的是逻辑推理和证明的过程。什么是带环链表带环链表链表最后一个结点的指针域不是指向空指针,而是指向链表之前的结点,这样就形成了环状的链表结构。... [详细]

  • 就如数字6一样结构,如何检测是否有6下部○呢,并且求交叉点位置思路使用快慢指针(一个一次走2步,一个走1步),若快慢指针第一次相遇,则有慢指针路程s=a+b快指针路程2s=a+b+nRs=nR长度 L=a+b+c=nR+c... [详细]

相关标签
  

闽ICP备14008679号