学习日记/2/15

今天,准备复习一下,刚开始复习,从搜索开始,发现我去,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今天就到这把,明天再复习一点

把二叉树看看

明天见!

 

你可能感兴趣的:(学习,深度优先,算法)