dfs和bfs

dfs

** i不要设为全局变量**

图的遍历

图的遍历

void dfs(int x){
    f1[x]=1;
    cout<<x<<" ";
    for(int i=0;i<e[x].size();i++){
        int d=s[e[x][i]].v;
        if(!f1[d]){
            dfs(d);
        }
    }
}

在n个数中取m个数

在n个数中算出任意m个数的和

先写dfs的函数,存储现在检索到第几个数,取了多少个数,以及当前数字和

void dfs(long long x,long long num,long long sum){
    if(num==m){
        s.insert(sum);
        return ;
    }
    for(int i=x+1;i<=N+num-m+1;i++){
        dfs(i,num+1,sum+a[i]);
    }
}

将n个数排列

将1~n的数进行排列再输出

void dfs(int x){
    if(x==n){
       for(auto i:a){
           cout<<i<<" ";
       }
       cout<<"\n";
        return ;
    }
    for(int i=1;i<=n;i++){
        if(f[i]==1)
            continue;
        a.push_back(i);
        f[i]=1;
        dfs(x+1);
        f[i]=0;
        a.pop_back();
    }
}

这里要注意每次判断该数字是否被选择并存在vector里,但回溯过程要注意恢复

n个数字可以取出多少种组合

这个题可以用二进制模拟写,也可以用dfs写

void dfs(int ans){
    if(ans>n)
    {
        for(int i=1;i<=n;i++){
            if(a[i])
                cout<<i<<" ";
        }
        cout<<endl;
    }
    else{
        a[ans]=1;
        dfs(ans+1);
        a[ans]=0;
        dfs(ans+1);
    }
}

这个要模拟所有位置是否被选,二进制模拟代码更为简单

将n个物品放置在m个容器中

dfs函数是存储现在已经放了多少个容器,以及上一个容器存了多少个物品

void dfs(int i,int n){
    long long j;
    if(i==N){
        if(M-all>=n)
            ans++;
    }
    else{
        for(j=n;j<=M;j++){
            all+=j;
            dfs(i+1,j);
            all-=j;
        }
    }
}

这个要注意下一次搜索时要删除这次搜索产生的影响,all存储的是已经把多少个物品放进去了,所以本次搜索存进去的数字要删掉

迷宫问题

寻找可以走的方向,p[i]和q[i]由寻找方向决定

int p[]={0,1,0,-1,0};
int q[]={0,0,1,0,-1};
void dfs(int x,int y){
    if( f[x][y] ) return ;
    f[x][y] = 1;
    for( int i = 1 , fx , fy ; i <= 4 ; i ++ )
    {
        fx = x + p[i] , fy = y + q[i];
        if( fx >= 1 && fy >= 1 && fx <= n && fy <= m && c[fx][fy] != '#' )
            dfs( fx , fy );
    }
}

将寻找过的点标记一下,避免两点反复寻找

二进制模拟

bfs

图的遍历

图的遍历

void bfs(int x){
    queue<int>q;//创建队列
    q.push(x);//将第一层放在队列中
    cout<<x<<" ";
    f2[x]=1;//这个点已经被查找
    while(!q.empty()){//队列不空就继续查找
        int in=q.front();//当前找上一层未被查找的第一个点
        for(int i=0;i<e[in].size();i++){//把它的子节点遍历一遍
            int d=s[e[in][i]].v;//
            if(!f2[d]){//当前这个节点没有被查找
                q.push(d);//将这个点存进队列,找他的子节点
                cout<<d<<" ";
                f2[d]=1;//这个点已经被找过了
            }
        }
        q.pop();//这个点已经被找过了
    }
}
posted @ 2022-07-13 19:23  zyzzzzlh  阅读(58)  评论(0)    收藏  举报