周报1——浅谈DFS算法及其应用

版权声明:这是ZYF老师的劳动成果,希望能得到你们的支持,转载请链接,谢谢配合! https://blog.csdn.net/qq_41332995/article/details/86627448

        首先自我介绍,我叫ZYF,来自广东中山(因孙中山而得名),是一个七年级的学生,目前在中山纪念中学学习信息学,主修Pascal,也会C++。

        这是周报的新起点,我将会在每周定期更新,如有时间冲突也会补上,谢谢大家的支持。

        这周我们来谈一谈最基础的入门算法——DFS。

        想必DFS大家并非陌生,不管是背过模板还是做过题,都会或多或少了解DFS。但是我却对DFS有自己的看法与了解。

        DFS,全名是深度优先搜索。顾名思义,它使用的是深度优先遍历。 深度优先搜索的过程是:

        (1)访问顶点V

        (2)依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;

        (3)如果有顶点尚未访问,会从当点重新进行深度优先遍历,直到所有点被遍历。

        说了这么多干货,我们看几张图来了解过程:

        这时上面的粉色部分,便是DFS极其重要的一步:回溯

        回溯需要注意什么:

        1.改变状态(否则会有答案错误),回到搜索前的状态。

        2.改变参数,使DFS能正常结束。

        听了这么多,是否了解DFS呢?

        再来一点注意事项:一定要有结束条件!一定要有结束条件!一定要有结束条件!(重要的事情说三遍)

        假如你没有结束条件,程序只会无休止的运行下去。

        这是许多人会问:DFS这么慢,为什么要用呢?

        1.DFS是某些正解算法的基础(比如DP),甚至能A掉某些题(但是数据会非常水)。

        2.DFS可以拿到部分分(尤其是DP),假如没有想出正解或者不确定正解,可以用DFS拿到能拿的分。

        3.许多题目加了剪枝就可以过(大多数是水过的),成为正解。

        4.提高组常用的对拍,用来检测程序正确性。

        一个简单的模板:

procedure search(参数表);
begin
           if 到达目标
           begin
                更新答案;
                退出;
           end
           else
           begin
                search(改变参数);
                回溯;
           end; 
end;

        当然,你也可以用数据结构存储参数,实现改变参数的目的。

        例题:迷宫问题

        题目大意:给你一个N*N的地图,某些点有障碍物,每次可沿点上下左右移动一格,求起点到终点的路径总数。

        分析:一道经典的DFS题,深度优先遍历找到所有的路径,并统计答案。

        参考程序:(抱歉我是P党)

const
        ff:array[1..4,1..2]of longint=((1,0),(-1,0),(0,1),(0,-1));
var
        x,y,ans,sx,sy,fx,fy,n,m,t,i:longint;
        bz:array[-1..1000,-1..1000] of boolean;
function check(shu1,shu2:longint):boolean;
begin
        if(shu1 in[1..n]) and(shu2 in[1..m]) then exit(true);
        exit(false);
end;
procedure search(x,y:longint);
var
        ii,xx,yy:longint;
begin
        xx:=0;
        yy:=0;
        if (x=fx) and (y=fy) then
        begin
                ans:=ans+1;
                exit;
        end
        else
        begin
                for ii:=1 to 4 do
                begin
                        xx:=x+ff[ii,1];
                        yy:=y+ff[ii,2];
                        if check(xx,yy)=true then
                        begin
                                if bz[xx,yy]=false then
                                begin
                                        bz[xx,yy]:=true;
                                        search(xx,yy);
                                        bz[xx,yy]:=false;
                                end;
                        end;
                end;
        end;
end;
begin
        
        readln(n,m,t);
        readln(sx,sy,fx,fy);
        bz[sx,sy]:=true;
        for i:=1 to t do
        begin
                readln(x,y);
                bz[x,y]:=true;
        end;
        search(sx,sy);
        writeln(ans);
        
end.

        推荐例题:LG P1219 P1101 P1019 P1605 P1040 P1092 (试炼场链接:洛古试炼场)(题目在普及练习场2.7)

        好了,本周周报就到此为止,下周的主题是:关于剪枝那些事。

猜你喜欢

转载自blog.csdn.net/qq_41332995/article/details/86627448