今天,准备复习一下,刚开始复习,从搜索开始,发现我去,bfs根本没学,okbfs听了半天听懂了
和dfs用递归解决不一样的,dfs的方式是在一条路上路直接到底。把每路都试一遍
bfs就是纵向的,一层的往下找,不是一条一条路的寻找了,是全方位的覆盖。
但是bfs要用到队列来保存每条路,要每次取队首来更新队列。
ok那就把队列拿下吧
队列和栈其实查不都就是,栈可以用更方便的顺序存储解构来,实现,但是队列的先进先出就难以实现了,所以对链表的运用是队列必不可少的技能
先来一个栈的完整实现
#include
#include
typedef struct ldui{
int data;
struct ldui* next;
}node;
node* top=NULL;
void push(int l){
if(top==NULL){
node* p=malloc(sizeof(node));
p->data=l;
p->next=NULL;
top=p;
}
else{
node* jk=malloc(sizeof(node));
jk->data=l;
jk->next=top;
top=jk;
}
}
void pop(){
if(top==NULL){
printf("false");
}
else{
node* l=top;
if(l!=NULL){
top=l->next;
}
else{
top=NULL;
}
free(l);
}
}
void showall(){
node* km=top;
while(km->next!=NULL){
printf("%d\n",km->data);
km=km->next;
}
}
int main(){
int k;
for(int y=1;y<=10;y++){
scanf("%d",&k);
push(k);
}
pop();
showall();
return 0;
}
没有啥的难点就是看你如何,给这个堆赋予功能 ,应为top,是指向最后一个进入的,所以就成为了栈。那么显然我们可以小小的一改,那他就不是栈就变成了队列了,
1把top指向最前面的数据,输出的时候也是从top开始的
2再定一个base的指针指向最后一个数据,新的数据加入,就可以直接找到队列的尾吧了,很节省时间
就这末小小的改动就可以完成由栈到,队列的变化
上代码看看
#include
#include
typedef struct ldui{
int data;
struct ldui* next;
}node;
node* top=NULL;
node* base=NULL;
void push(int l){
if(top==NULL&&base==NULL){
node* p=malloc(sizeof(node));
p->data=l;
p->next=NULL;
base=p;
top=p;
}
else{
node* jk=malloc(sizeof(node));
jk->data=l;
jk->next=NULL;
base->next=jk;
base=jk;
}
}
void pop(){
if(top==NULL){
printf("false");
}
else{
node* l=top;
if(top->next==NULL){
base=NULL;
}
top=l->next;
free(l);
}
}
void showall(){
node* km=top;
while(km!=NULL){
printf("%d\n",km->data);
km=km->next;
}
}
int main(){
int k;
for(int y=1;y<=10;y++){
scanf("%d",&k);
push(k);
}
showall();
return 0;
}
其实就对上面的代码改了一点了逻辑的关系,
如新入的就会被前辈们的next给穿起来,而不是后浪推前浪,的把前辈们踩再脚下(我想当后浪)
你会发现,二者的关联,top依旧是核心的地位,是记录关键位置必不可少的指针,其实你也可以把top和base方在一个新的定义的类型里面,我这是直接拿到外面当全局变量了,反正这东西,看着感觉很复杂,但是写的多了,理解上来了那还不是轻松的拿捏,当然用链表有好处有环处,时间确实复杂,由于有对内存的一个申请。
ok链表和队列,又是一遍复习,二叉树以及树,与链表有关的又是有了一点的精进。
来看看dfs到底如何去实现吧,总得用用才是真的。
小 H 在一个划分成了 n \times mn×m 个方格的长方形封锁线上。 每次他能向上下左右四个方向移动一格(当然小 H 不可以静止不动), 但不能离开封锁线,否则就被打死了。 刚开始时他有满血 66 点,每移动一格他要消耗 11 点血量。一旦小 H 的血量降到 00, 他将死去。 他可以沿路通过拾取鼠标(什么鬼。。。)来补满血量。只要他走到有鼠标的格子,他不需要任何时间即可拾取。格子上的鼠标可以瞬间补满,所以每次经过这个格子都有鼠标。就算到了某个有鼠标的格子才死去, 他也不能通过拾取鼠标补满 HP。 即使在家门口死去, 他也不能算完成任务回到家中。
地图上有五种格子:
0
:障碍物。
1
:空地, 小 H 可以自由行走。
2
:小 H 出发点, 也是一片空地。
3
:小 H 的家。
4
:有鼠标在上面的空地。
小 H 能否安全回家?如果能, 最短需要多长时间呢?
第一行两个整数 n,mn,m, 表示地图的大小为 n \times mn×m。
下面 nn 行, 每行 mm 个数字来描述地图。
一行, 若小 H 不能回家, 输出 -1
,否则输出他回家所需最短时间。
输入 #1复制
3 3 2 1 1 1 1 0 1 1 3
输出 #1复制
4
对于所有数据,1 \le n,m \le 91≤n,m≤9。
2021.9.2 增添一组 hack 数据 by @囧仙
题目出自:P2802 回家 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目标的难度确实挺小的,写起来就是十分的痛苦(手写队列真的有点要命)
不可以扩展的点入队
用的点用了就出队
判断结束的条件就是点的值为3前提是可以走到3
要注意的是
到了一点hp降为了1,且没有回复,ok路已经断了
无论接下来往啥点走,都会死(就算是到家时候的HP也要大于0)
有的点要重复的走,因为要补血,可能不补就嗝屁了,
但是补血之后再来到经历过的点一定是血要比之前多的(不然补了个屁)
遇到的第一个符合要求的点直接输出,步数是一步一步的增的越早的出现表示,同步数的情况下到达了家。(和dfs的区分了)
最现出现的一定是最短的,可能会有与之相同的但是绝对不会有更小的。
ok上代码
#include
#include
int map[15][15];
int maps[15][15];//记录到这位置的最大血量
int xl[4]= {0,0,1,-1};
int yl[4]= {1,-1,0,0}; //走得到方向盘
typedef struct ldui//用队列记录点,一个单元
{
int x;
int y;
int hp;
int step;
struct ldui* next;
} node;
node* top=NULL;
node* base=NULL;//直接把头和尾定义出来
void push(int c,int v,int hj,int b)
{
if(top==NULL&&base==NULL)
{
node* p=malloc(sizeof(node));
p->x=c;
p->y=v;
p->hp=b;
p->step=hj;
p->next=NULL;
base=p;
top=p;
}
else
{
node* jk=malloc(sizeof(node));
jk->x=c;
jk->y=v;
jk->hp=b;
jk->step=hj;
jk->next=NULL;
base->next=jk;
base=jk;
}
}
void pop()
{
if(top==NULL&&base==NULL)
{
printf("false");
}
else
{
node* l=top;
if(top->next==NULL)
{
base=NULL;
}
top=l->next;
free(l);
}
}
int main()
{
int n,m;
int i=0;
scanf("%d%d",&n,&m);
for(int h=1; h<=n; h++)
{
for(int g=1; g<=m; g++)
{
scanf("%d",&map[h][g]);
if(map[h][g]==2){
push(h,g,0,6);
}
}
}
while(base!=NULL)//直接对尾进行检查,空的就是队列空了,查完了
{
int X=top->x;
int Y=top->y;
int HP=top->hp;
int bu=top->step;
pop();
if(map[X][Y]==3)
{
printf("%d\n",bu);
i++;
break;
}
if(HP>1)//血没大于1,走那都是死
{
for(int gh=0; gh<4; gh++)
{
int lx=X+xl[gh];
int ly=Y+yl[gh];
if(lx<=n&&lx>=1&&ly<=m&&ly>=1)
{
if(map[lx][ly]==1||map[lx][ly]==3)
{
if(maps[lx][ly]
代码有点长,没办法c语言,带这种自定义的结构,确实要写好多来实现这些的功能,
我还简化了很多的操作,而且bfs本身的代码量就不小
疯狂的敲和测试差点把人送了,还是要细心,一点点的错误可以让你,难受半天
ok今天就到这把,明天再复习一点
把二叉树看看
明天见!