基础dfs和bfs

搜索

bfs

bfs 名字是广度优先搜索
核心思想就是我从一个节点出发,先遍历一遍距离为1的,再遍历距离为2的……

这个如果看不懂(就直接退役吧)当然还有别的办法:

上例题看代码!
马的遍历
我们先来看题意,就是看你的image到达每一格需要的最少步数
那么我们想,我们可以让image儿先走一步,然后看看走一步的那些点有哪些,让它们的ans[i][j]=已经走的步数,vis[i][j]=1 我们记录下刚才走到了哪里,然后接着上一步继续走,然后我们再让此时的ans[i][j]=已经走的步数,vis[i][j]=1,直到image儿不能再往任何地方走了为止

int n,m,u,v;
queue <int> x,y;
int dx[8]={-2,-2,2,2,1,-1,1,-1};
int dy[8]={-1,1,-1,1,2,-2,-2,2};
int ans[410][410];
bool vis[410][410];
void bfs(){
    while(!x.empty()){
        int x1=x.front(),y1=y.front();
        x.pop(),y.pop();
        for(int i=0,x2,y2;i<8;i++){
            x2=x1+dx[i],y2=y1+dy[i]; 
            if(vis[x2][y2]||x2<1||y2<1||x2>n||y2>m) continue;
            vis[x2][y2]=true;
            // cout<<x2<<" "<<y2<<endl;
            ans[x2][y2]=ans[x1][y1]+1;
            x.push(x2),y.push(y2);
        }
    }
}
int main(){
    // freopen("1.out","w",stdout);
    ios::sync_with_stdio(false);
    cin>>n>>m>>u>>v;
    memset(ans,-1,sizeof ans);
    x.push(u),y.push(v);
    vis[u][v]=1;
    ans[u][v]=0;
    bfs();
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++) printf("%-5d",ans[i][j]);
        printf("\n");
    }//注意场宽!!
    return 0;
}

这里就是代码了

广搜有几个技巧
1.用queue记录下当前的状态
2.不走回头路
3.遍历可以走的地方时用dx,dy表示,写一个循环

这就是广搜,应用主要集中在图论
spfa,dijkstra都会用到广搜

深搜

深搜就是一个非常重要的东西了,但是它确实很麻烦,dfs,学名深度优先搜索,简称就是一步搜到底

这个真的没什么可以讲的,只有在题里面才能体会的到

洛谷P1036 选数
一道经典的深度优先搜索题
题意就是n个数选m个,算一算它们的和是不是质数

质数筛之前的博客中写过,这里不再赘述
那这个问题我们应该如何解决呢?

我们发现,我们可以循环着去取数
但是选过的不能再选,所以我们的可以
void dfs(int now,int tot,int first)
三个变量分别表示 现在已经取了几个数,现在取得数的和,现在该取第first个数了
搜的边界显然是now== m时或者first==n时check(tot)
那么我们的代码也就自然而然的出来了

bool prime(int x){
    if(x==1) return 0;
    for(int i=2;i*i<=x;i++) if(x%i==0) return 0;
    return 1;
}

void dfs(int now,int sum,int first){
    if(now==k){
        if(prime(sum)) ans++;
        return;
    }
    for(int i=first;i<=n;i++){
        if(!vis[i]){
            vis[i]=true;
            dfs(now+1,sum+a[i],i);
            vis[i]=false;/*这里的vis变量处理是关键,可以好好理解一下*/
        }
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>a[i];
    dfs(0,0,1);
    cout<<ans;
}

理论来说搜索的知识并不多,但是难度和思想还是有的,多刷题,是学好搜索的必经之路

posted @ 2021-09-22 21:53  RevolutionBP  阅读(22)  评论(0编辑  收藏  举报