『BFS与DFS:搜索专题』

版权声明:随你转载,你开心就好(记得评论和注明出处哦) https://blog.csdn.net/Prasnip_/article/details/81037136

<前言>
暴力搜索不需要解释


<更新提示>

<第一次更新>


<正文>

DFS

dfs,全名depth-first-search,即深度优先搜索。如其名,其最大的特点就是以深度为优先条件对搜索树的节点进行拓展,以栈来维护其搜索次序。当然,多数dfs用系统栈实现——递归。
概念不用多说,以例题和代码实现为重。

例题
1

8皇后问题
题目描述
在一个n×n的棋盘上放置n个国际象棋中的皇后,要求所有的皇后之间都不形成攻击。请你给出所有可能的排布方案数。
输入格式
一个整数n
输出格式
一个整数表示方案数
样例数据
input
4
output
2
数据规模与约定
n<=8
时间限制:
1s
1s
空间限制:
256MB

解析

经典dfs搜索与回溯的入门题,其搜索策略如下:
按行放置每一个皇后,并使用三个数组标记同列,两条对角线是否有其他的皇后存在,如果存在,则为不合法的放置,如果合法,继续递归,尝试放置下一个皇后。直至放置第n个皇后,方案数增加。调用递归时注意标记数字,递归结束记得回溯:清除数组标记。

代码实现如下:

#include<bits/stdc++.h>
using namespace std;
int n,tot=0;
bool line[1000]={},ri[1000]={},le[1000]={};
void solve(int row)
{
    if(row==n)
    {
        tot++;
        return ;
    }
    for(int i=0;i<n;i++)
    {
        if(!(line[i]||ri[row-i+n]||le[row+i]))
        {
            line[i]=ri[row-i+n]=le[row+i]=true;
            solve(row+1);
            line[i]=ri[row-i+n]=le[row+i]=false;
        }
    }
}
int main()
{
    cin>>n;
    solve(0);
    cout<<tot<<endl;
    return 0;
}
2

工作分配问题
题目描述
设有n件工作分配给n个人。将工作i 分配给第j 个人所需的费用为Cij。试设计一个算法,为每一个人都分配1 件不同的工作,并使总费用达到最小。 设计一个算法,对于给定的工作费用,计算最佳工作分配方案,使总费用达到最小。
输入格式
第一行有1 个正整数n (1≤n≤20)。
接下来的n行,每行n个数,表示工作费用。
输出格式
一个整数,表示最小总费用
样例数据
input
3
10 2 3
2 3 4
3 4 5
output
9
数据规模与约定
时间限制:
1s
1s
空间限制:
256MB

解析

鉴于数据量极小,考虑直接暴力搜索即可,其策略如下:利用递归搜索每一种情况。递归的形参为:深度(人数),花费。需要一个数组来标记某个人是否已经工作,避免重复,当搜索的人数大于n时,查看能否更新答案。其剪枝优化如下:当形参花费已经大于之前得出的答案时,返回递归。
代码实现如下:

#include<bits/stdc++.h>
using namespace std;
const int INF=999999999;
int Min=INF,spend[1080][1080],vis[1080]={},n;
void dfs(int depth,int sum)
{
    if(sum>Min)return;
    if(depth>n)
    {
        Min=min(Min,sum);
    }
    for(int i=1;i<=n;i++)
    {
        if(!vis[i])
        {
            vis[i]=1;
            dfs(depth+1,sum+spend[depth][i]);
            vis[i]=0;
        }
    }

}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cin>>spend[i][j];
        }
    }
    dfs(1,0);
    cout<<Min<<endl;
}
3

最佳调度问题
题目描述
假设有n 个任务由k 个可并行工作的机器完成。
完成任务i 需要的时间为ti。
试设计一个算法找出完成这n 个任务的最佳调度,使得完成全部任务的时间最早。 一旦任务i由某台机器完成,中途不能更换机器。
编程任务:
对任意给定的整数n 和k,以及完成任务i 需要的时间为ti,i=1~n 。编程计算完成这n个任务的最佳调度
输入格式
第一行有2 个正整数n 和k。
第2 行的n 个正整数是完成n 个任务需要的时间。
输出格式
完成全部任务的最早时间。
样例数据
input
7 3
2 14 4 16 6 5 3
output
17
input
5 2
8 9 3 7 7
output
17
数据规模与约定
保证
n<=20,k<=10
n<=20,k<=10

时间限制:
1s
1s
空间限制:
256MB

解析

依然使用深搜枚举每一种情况。递归的形参设置也和上一题相同:深度(已经分配的任务数),已经花费的时间。我们建立Time数组,Time[i]表示第I台机器工作的时间,总花费时间即max{Time[i]}(i=1~n),利用其方便深搜时的统计。对于本题,数据量较大,暴力搜索必然超时。我们需要两个剪枝和一个优化:
1)剪枝:在递归函数顶剪枝,如果答案已经比之前得出的某个答案大,返回。
2)剪枝:在递归时剪枝,如果机器i以前花费的时间加上这次递归调用需要花费的时间已经1大于之前得出的某个答案,跳过本次递归。(与剪枝1并不重复!!)
3)优化:将机器花费从大到小排序,更好的响应剪枝1。

代码实现如下:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define begin {
#define end } 
#define mset(name,num) memset(naem,num,sizeof(num))
using namespace std;
inline void read(int &k)
begin
    int x=0,w=0;char ch;
    while(!isdigit(ch))begin w|=ch=='-';ch=getchar(); end
    while(isdigit(ch))begin x=(x<<3)+(x<<1)+(ch^48);ch=getchar(); end
    k=(w?-x:x);return;
end
int n,k,Spend[800]={},Time[800]={},Ans=0x3f3f3f3f;
inline bool cmp(int a,int b)begin return a>b; end 
inline void input()
begin
    read(n);read(k);
    for(int i=1;i<=n;i++)read(Spend[i]);
end
inline void Search(int depth,int Usedtime)
begin
    if(depth>n)
    begin
        Ans=min(Ans,Usedtime);
        return;
    end 
    if(Usedtime>=Ans)return;
    for(int i=1;i<=k;i++)
    begin
        if(Time[i]+Spend[depth]<Ans)
        begin
            Time[i]+=Spend[depth];
            Search(depth+1,max(Usedtime,Time[i]));
            Time[i]-=Spend[depth];
        end
    end
end
int main()
begin
    input();
    sort(Spend+1,Spend+n+1,cmp);
    Search(1,0);
    cout<<Ans<<endl;
    return 0; 
end

(请忽略清奇的码风)

4

因式分解
题目描述
将大于1的自然数n进行因式分解,满足           
n=a1∗a2∗a3∗..am
编一程序,对任意的自然数
n(1 < n ≤ 2,000,000,000)
n(1 < n ≤ 2,000,000,000)
,求 n的所有形式不同的因式分解 方案总数。
如 n=12,共有8种分解方案,他们分别是:
   12=12
   12=6×2
   12=4×3
   12=3×4
   12=3×2×2
   12=2×6
   12=2×3×2
   12=2×2×3
输入格式
一个整数n
输出格式
一个整数m,代表不同的因式分解的方案总数。
样例数据
input
12
output
8
数据规模与约定
时间限制:
1s
空间限制:
256MB

解析

搜索技巧:预处理。
我们预处理出n的所有因数,并记录在f数组里,并将其从小到大排序。其搜索策略如下:利用因子表枚举n的每一个因子,并递归地利用n的因子表继续枚举它们的因子,直至枚举至1的因子,返回并将方案数增加即可。
代码实现如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define begin {
#define end } 
#define mset(name,num) memset(naem,num,sizeof(num)
using namespace std;
inline void read(int &k)
begin
    int x=0,w=0;char ch;
    while(!isdigit(ch))begin w|=ch=='-';ch=getchar(); end
    while(isdigit(ch))begin x=(x<<3)+(x<<1)+(ch^48);ch=getchar(); end
    k=(w?-x:x);return;
end
int ans=0,n,f[100080]={},t=0; 
void dfs(int k)
{
    if(k==1)begin ans++;return; end
    for(int i=1;i<=t&&f[i]<=k;i++)if(k%f[i]==0)dfs(k/f[i]);
}
int main()
begin
    cin>>n; 
    for(int i=2;i*i<=n;i++)
    begin
        if(n%i==0)
        begin
            f[++t]=i;
            if(i*i!=n)f[++t]=n/i;
        end 
    end
    f[++t]=n;
    sort(f+1,f+t+1);
    dfs(n);
    cout<<ans;
end
小结

dfs一般没有固定的模板,需要我们根据题目建立模型,制定搜索策略,特别是递归函数形参的设置,需要深刻考虑。在遇到解题策略不明的其他题目时,也可以考虑暴力搜索答案得分。dfs的基本技巧与剪枝优化如下:
1)可行性剪枝:检查目前的答案是否符合要求或题目限制。
2)最优化剪枝:检查答案是否已经比之前得出的答案更差。
3)预处理:简化搜索代码量与时间复杂度
4)记忆化:空间换时间,记录已经搜索过的状态。
5)数学推导:从而得出1)或2)的剪枝优化。

dfs搜索时的策略一定要明确,先思考,再敲代码,千万不能盲目下手,只会浪费时间。

BFS

bfs,全名breath-first-search,即广度优先搜索。如其名,其最大的特点就是以层数为优先条件对搜索数的节点进行逐层拓展,以队列来维护其搜索次序。bfs用stl自带队列或手写队列实现。
bfs概念与实现入门见福州集训Day2,本篇以例题讲解为重。

例题
1

奇怪的电梯
题目描述
有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第i层楼(1<=i<=N)上有一个数字Ki(0<=Ki<=N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5代表了Ki(K1=3,K2=3,……),从一楼开始。在一楼,按“上”可以到4楼,按“下”是不起作用的,因为没有-2楼。那么,从A楼到B楼至少要按几次按钮呢?
输入格式
输入文件共有二行,第一行为三个用空格隔开的正整数,表示N,A,B(1≤N≤200, 1≤A,B≤N),第二行为N个用空格隔开的正整数,表示Ki。
输出格式
输出文件仅一行,即最少按键次数,若无法到达,则输出-1。
样例数据
input
5 1 5
3 3 1 2 5
output
3
数据规模与约定
时间限制:
1s
空间限制:
256MB

分析

bfs入门题,搜索策略清晰,直接依据题意,构建距离数组dis,标记数组vis,利用while循环bfs搜索即可,手写队列维护。注意,本题的细节为:当a=b时,直接输出0。
代码实现如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define begin {
#define end } 
#define mset(name,num) memset(naem,num,sizeof(num))
using namespace std;
inline void read(int &k)
begin
    int x=0,w=0;char ch;
    while(!isdigit(ch))begin w|=ch=='-';ch=getchar(); end
    while(isdigit(ch))begin x=(x<<3)+(x<<1)+(ch^48);ch=getchar(); end
    k=(w?-x:x);return;
end
int n,a,b,move[280]={},head=1,tail=0,vis[280]={},dis[280]={},q[280]={};
int main()
begin
    read(n);read(a);read(b);
    for(int i=1;i<=n;i++)read(move[i]);
    vis[a]=1,dis[1]=0;
    q[++tail]=a;
    while(head<=tail)
    begin
        int temp=q[head++];
        if(temp==b)break;
        if(temp+move[temp]<=n&&vis[temp+move[temp]]==0)
        begin
            vis[temp+move[temp]]=1;
            dis[temp+move[temp]]=dis[temp]+1;
            q[++tail]=temp+move[temp];
        end
        if(temp-move[temp]>=1&&vis[temp-move[temp]]==0)
        begin
            vis[temp-move[temp]]=1;
            dis[temp-move[temp]]=dis[temp]+1;
            q[++tail]=temp-move[temp]; 
        end
    end
    if(a==b)begin cout<<0<<endl; return 0; end
    else
    begin 
        if(dis[b]==0)cout<<-1<<endl;
        else cout<<dis[b]<<endl;
        return 0;
    end
end
2

青铜莲花池
题目描述
Farmer John为了满足宁智贤对美的享受而安装了人工湖。矩形的人工湖分成M行N列(1 <= M <= 30; 1 <= N <= 30)的方形小格子。有些格子有美丽的荷叶,有些有岩石,剩下的格子有的只是美丽的蓝色湖水。 宁智贤通过从一片荷叶跳到另一片荷叶上来练习芭蕾。它现在正站在一片荷叶上(看输入数据了解具体位置)。它希望通过在荷叶上跳跃来到达另一片荷叶。它既不能跳到水里也不能跳到岩石上。 只有新手才会感到吃惊:宁智贤的跳跃有点类似国际象棋中马那样的移动,在一个方向上(如水平方向)移动M1(1 <= M1 <= 30)“格”,然后再在另一个方向上(如竖直方向)移动M2 (1 <= M2 <= 30; M1 != M2)格,所以宁智贤有时可能有多达8中的跳跃选择。
给出池塘的构造以及宁智贤跳跃的形式,找出宁智贤从一个位置移动到另一个位置所需的最小的跳跃次数。这个跳跃对于所给的测试数据总是可能的。
输入格式
第 1 行: 四个空格分开的整数: M, N, M1, 和 M2
第 2 至 M+1行: 第i+1行用N个空格分开的整数描述池塘第i行,0表示水,1表示荷叶,2表示岩石,3表示宁智贤现在站的那块荷叶,4表示跳跃的终点。
输出格式
一个整数,是宁智贤从一块荷叶跳到另一块荷叶所需的最小的跳跃数。
样例数据
input
4 5 1 2
1 0 1 0 1
3 0 2 0 4
0 1 2 0 0
0 0 0 1 0

输入说明:

宁智贤在第二行的左边开始;她的目的地在第二行的右边。池塘中有几块荷叶和岩石。
output
2

输出说明:

机智的宁智贤跳到了(1,3)的荷叶上,再跳到目的地。
数据规模与约定
保证
1≤M≤30,1≤N≤30
1≤M≤30,1≤N≤30
时间限制:
1s
空间限制:
256MB

分析

看到最短距离,又没有边权,不是最短路,显然想到具有最短距离搜索性质的bfs。本题为迷宫类bfs,可以构造方位数组减轻代码量。其搜索策略明确:选择所有可拓展的位置拓展即可。
代码实现如下:

#include<bits/stdc++.h>
using namespace std;
int n,m,m1,m2;
int Map[5000][5000]={},dx[10],dy[10],visited[5000][5000],road[5000][5000]={};
int beginx,beginy,endx,endy,head=0,tail=0;;
struct QUEUE
{
    int x,y;
}que[100080]={};
inline int read()  
{  
    int X=0,w=0; char ch=0;  
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}  
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();  
    return w?-X:X;  
}
inline void input()
{
    m=read();n=read();
    m1=read();m2=read();
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            Map[i][j]=read();
        }
    }
}  
inline void build_Map()
{
    dx[0]=dx[1]=dy[4]=dy[6]=m1;
    dx[2]=dx[3]=dy[5]=dy[7]=-m1;
    dx[4]=dx[5]=dy[0]=dy[2]=m2;
    dx[6]=dx[7]=dy[1]=dy[3]=-m2;
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(Map[i][j]==2)Map[i][j]=0;
            if(Map[i][j]==3){beginx=i;beginy=j;}
            if(Map[i][j]==4){endx=i;endy=j;}
        }
    }
}
inline void bfs()
{
    que[++tail].x=beginx;que[tail].y=beginy;
    visited[beginx][beginy]=1;
    while(head++<tail)
    {
        int x=que[head].x,y=que[head].y;
        for(int i=0;i<8;i++)
        {
             if(!visited[x+dx[i]][y+dy[i]]&&Map[x+dx[i]][y+dy[i]])
            {
                road[x+dx[i]][y+dy[i]]=road[x][y]+1;
                if(x+dx[i]==endx&&y+dy[i]==endy) return;
                que[++tail].x=x+dx[i];que[tail].y=y+dy[i];
                visited[x+dx[i]][y+dy[i]]=1;
            }
        }
    }
}
inline void output()
{
    cout<<road[endx][endy]<<endl;
}
int main()
{
    input();
    build_Map();
    bfs();
    output();
    return 0;
}
3

显示图像
题目描述
古老的显示屏是由N×M个象素(Pixel)点组成的。一个象素点的位置是根据所在行数和列数决定的。例如P(2,1)表示第2行第1列的象素点。那时候,屏幕只能显示黑与白两种颜色,人们用二进制0和1来表示。0表示黑色,1表示白色。当计算机发出一个指令:P(x,y)=1,则屏幕上的第x行第y列的阴极射线管就开始工作,使该象素点显示白色,若P(x,y)=0,则对应位置的阴极射线管不工作,象素点保持黑色。在某一单位时刻,计算机以N×M二维01矩阵的方式发出显示整个屏幕图像的命令。 例如,屏幕是由3×4象素点组成,在某单位时刻,计算机发出如下命令:
0001
0011
0110
则屏幕图像为:
这里写图片描述

(假设放大后,一个格子表示一个象素点)
由于未知的原因,显示黑色的象素点总是受显示白色的象素点的影响——可能是阴极射线管工作的作用。并且,距离越近,影响越大。这里的距离定义如下:设有象素点P1(x1,y1)和象素点P2(x2,y2),则它们之间的距离D(P1,P2):D(P1,P2)=|x1-x2|+|y1-y2| 在某一时刻,计算机发出显示命令后,科学家们期望知道,每个象素点和其最近的显示白色的象素点之间的最短距离是多少——科学家们保证屏幕上至少有一个显示白色的象素点。 上面的例子中,象素P(1,1)与最近的白色象素点之间的距离为3,而象素P(3,2)本身显示白色,所以最短距离为0。
输入格式
第一行有两个数字,N和M (1<=N,M<=1000),表示屏幕的规格。
以下N行,每行M个数字,0或1。为计算机发出的显示命令。
输出格式
输出文件有N行,每行M个数字,中间用1个空格分开。第i行第j列的数字表示距象素点P(i,j)最近的白色象素点的最短距离。
样例数据
input
3 4
0001
0011
0110
output
3 2 1 0
2 1 0 0
1 0 0 1
数据规模与约定
时间限制:
1s
1s
空间限制:
256MB
注释
【数据范围】
对于30%的数据:
N×M≤10000
N×M≤10000

对于100%的数据:
N×M≤
1000
2
N×M≤1000*1000

分析

这道题的特殊性在于搜索的多源点,但鉴于最短曼哈顿距离性质,还是bfs。对于多源点,只需在输入时将所有黑色像素点直接加入队列,同时执行多颗搜索树的搜索,并使用同一个队列维护即可。由于这有违常规的bfs,可以想象为每一棵搜索树的根节点又同时都连结了一个共同的不存在的-1层节点,即总的根节点,每一棵搜索树都是总搜索树的子树。所以bfs仍然正常搜索不误。
代码实现如下:

#include<bits/stdc++.h>
using namespace std;
int n,m,tail=0,head=1;
struct MAP
{
    int x,y;
}q[100080]={};
bool vis[10800][10800];
int dis[10800][10800]={};
int dx[4]={0,0,-1,1},dy[4]={-1,1,0,0};
int main()
{
    memset(vis,true,sizeof(vis));
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        string line;
        cin>>line;
        for(int j=0;j<line.size();j++)
        {
            if(line[j]=='0')vis[i][j+1]=false;
            else dis[i][j+1]=0,vis[i][j+1]=true,q[++tail].x=i,q[tail].y=j+1;
        }
    }
    for(head=1;head<=tail;head++)
    {
        for(int i=0;i<4;i++)
        {
            int xx=q[head].x+dx[i],yy=q[head].y+dy[i];
            if(!vis[xx][yy])
            {
                dis[xx][yy]=dis[q[head].x][q[head].y]+1;
                vis[xx][yy]=1;
                q[++tail].x=xx;
                q[tail].y=yy;
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<m;j++)
        {
            cout<<dis[i][j]<<" ";
        }
        cout<<dis[i][m]<<endl;
    }
    return 0;
}
4

3.奇怪的机器人
(robot.pas/c/cpp)
【问题描述】
有一个奇怪的机器人,它被关在一个实验室里。
实验室是一个长方形,被分成了n行m列个格子,某些格子能走而有些不能
现在这个机器人每次能走到与他相邻的上下左右四个格子(如果相邻的格子能走的话),但是不同方向的花费不一样,往上,下,左,右四个方向走一次分别需要花费1,2,3,4块钱。
机器人在第x1行y1列的格子上,出口在x2行y2列的格子上,问你机器人想出去最少需要花多少钱?
【输入】
第一行两个用空格隔开的整数n和m
接下来n行,每行m个字符,表示地图
如果第i行j列个字符为’.’,表示这个地方能走,否则不能
最后一行四个用空格隔开的整数x1,y1,x2,y2
保证第x1行y1列和第x2行y2列一定是’.’
【输出】
一行一个整数,如果机器人能出去则为它最少需要花多少钱,否则为-1
【输入输出样例1】
4 4
….
.**.
..*.
….
3 2 3 4 11

【输入输出样例2】
1 3
.*.
1 1 1 3 -1

【数据范围】
1<=n,m<=50

解析

这道题的实质还是bfs,这道题的优秀之处在于他对于不同方向的移动有不同的花费,需要深入思考。引入了边权的参数后,迷宫类问题的bfs模板看似不行,实则还是这样。其搜索策略如下:对于边权的存在,绕路反而花费更小的可能也随之出现。我们放弃vis数组,对于一个节点,我们可以访问多遍,前提在于花费更少,这就类似于三角形松弛迭代,bfs就更像图论算法中的spfa。但代码仍然和bfs模板很像,实现难度很小。
代码实现如下:

#include<bits/stdc++.h>
using namespace std;
inline void read(int &k)
{
    int w=0,x=0;char ch;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    k=(w?-x:x);return;
}
int n,m,Map[80][80]={},stx,sty,enx,eny,spend[80][80],Max;
int head=1,tail=0;struct QUEUE{int x,y;}q[80*80]={};
int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1};
int main()
{
    //freopen("robot.in","r",stdin);
    //freopen("robot.out","w",stdout);
    read(n),read(m);
    memset(spend,10,sizeof(spend));
    Max=spend[1][1];
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            char temp;
            cin>>temp;
            if(temp=='*')Map[i][j]=0;
            else Map[i][j]=1;
        }
    } 
    read(stx),read(sty);
    read(enx),read(eny);
    spend[stx][sty]=0;
    q[++tail]=(QUEUE){stx,sty};
    while(head<=tail)
    {
        int tx=q[head].x,ty=q[head].y;
        head++;
        for(int i=1;i<=4;i++)
        {
            int px=tx+dx[i],py=ty+dy[i];
            if(px<1||py<1||px>n||py>m)continue;
            if(spend[tx][ty]+i<spend[px][py]&&Map[px][py])
            {
                spend[px][py]=spend[tx][ty]+i;
                q[++tail]=(QUEUE){px,py};
            }
        }
    }
    if(spend[enx][eny]!=Max)cout<<spend[enx][eny]<<endl;
    else cout<<-1<<endl;
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}
小结

bfs与dfs相比,就更规范了。每一道bfs题基本都是模板的运用或更改。但其仍有许多灵活之处,例如向图论算法的拓展,搜索路径的输出等,需要我们灵活掌握。bfs的优化相对更少一些,但也不代表没有。bfs的着重点在于对题目的分析,确认其是否应该使用bfs,需要怎样优化和更改。bfs的难题也有许多,例如磁带储存器(会专放一篇博客讲)等题,需要多加练习。

关于搜索专题的小结和考试的总结

关于搜索专题,基本上就结束了,对于A*,IDA*,迭代加深等更高级的搜索算法就留给以后再讲吧。NOIP普及组的搜索就以bfs和dfs为主,小结也写在上文了,希望NOIP能派上用场。这次考试是我暑假继集训考的最差的一次,只考了280分(满分400),主要问题在于过于执着写出正解和没能灵活运用代码技巧减轻代码量,真正考试时,任何能得分的方法都是好方法,暴力,打表,都是可以尝试的方法,不要局限于好好敲题,考试的时候,就某题算得不了满分,那你的目标就是尽你所能得到最高的分数,这就是搜索的信仰。


<后记>


<废话>

猜你喜欢

转载自blog.csdn.net/Prasnip_/article/details/81037136