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();//这个点已经被找过了
}
}

浙公网安备 33010602011771号