搜索
深度优先搜索(DFS)
以图(Graph)为例,深度优先搜索也称为深度优先周游(DFT),其具体的思想是:
先访问图中某个(未访问过的)结点v,然后选择一个v邻接到的未被访问过的结点w,再访问w,并按照同样的方法前进;当遇到一个所有邻接于它的结点都被访问过了的结点时,退回到已访问结点序列中最后一个拥有相邻结点未被访问过的结点,访问它的一个未被访问过的相邻结点u,再从u出发按相同的方式前进。当所有已被访问过的结点的相邻结点都被访问时,如果图中还有未被访问的顶点,则从另一未被访问过的顶点出发重复上述过程,直到图中所有顶点都被访问过时,周游结束。
问题示例
洛谷 p1706 全排列问题
题目描述
按照字典序输出自然数 1 到 n 所有不重复的排列,即 n 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。
输入格式
一个整数 n。
输出格式
由 1∼n 组成的所有不重复的数字序列,每行一个序列。
每个数字保留 5个场宽。
#include<bits/stdc++.h>
using namespace std;
int a[10],b[10];
int n,cnt=0;
void dfs(int i);
int main(){
cin>>n;
memset(b,0,sizeof(b));
dfs(0);
return 0;
}
void dfs(int i){
if(i==n) {
cnt++;
for(int j=1;j<=n;j++) printf("%5d",a[j]);
cout<<endl;
}
else{
for(int j=1;j<=n;j++)
if(!b[j]){
a[i+1]=j;
b[j]=1;
dfs(i+1);
b[j]=0;
}
}
}
广度优先搜索(BFS)
以图为例,广度优先搜索(BFS) 是连通图的一种遍历算法。这一算法也是很多重要的图的算法的原型。其中被广泛使用的有Dijkstra单源最短路径算法和Prim最小生成树算法等,其算法都采用了和广度优先搜索类似的思想。广搜是一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。而并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。
广度优先搜索常用于解决以下两类问题
1.从某个点出发,是否可以到达指定的点。
2.从某个点出发,求到达指定的点的最短的路径。
问题示例
洛谷 p1364 医院设置
题目描述
设有一棵二叉树,如图:
其中,圈中的数字表示结点中居民的人口。圈边上数字表示结点编号,现在要求在某个结点上建立一个医院,使所有居民所走的路程之和为最小,同时约定,相邻接点之间的距离为 1。如上图中,若医院建在1 处,则距离和 =4+12+2×20+2×40=136;若医院建在 3 处,则距离和 =81=4×2+13+20+40=81。
输入格式
第一行一个整数 n,表示树的结点数。
接下来的 nn 行每行描述了一个结点的状况,包含三个整数 w, u, ,v,其中 w 为居民人口数,u 为左链接(为 0 表示无链接),v 为右链接(为 0 表示无链接)。
输出格式
一个整数,表示最小距离和。
医院设置
#include<bits/stdc++.h>
using namespace std;
int a[101],g[101][101];
int main()
{
int n;
cin >> n;
int i,j,k,l,r;
memset(g,1,sizeof g);
for(i=1;i<=n;i++)
{
cin >> a[i] >> l >> r;
if(l>0) g[i][l]=g[l][i]=1;
if(r>0) g[i][r]=g[r][i]=1;
g[i][i]=0;
}
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
if(i!=k)
for(j=1;j<=n;j++)
if(i!=j && j!=k)
{
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}
int mixn=100000000,tot;
for(i=1;i<=n;i++)
{
tot=0;
for(j=1;j<=n;j++)
tot = tot+g[i][j]*a[j];
mixn=min(mixn,tot);
}
cout << mixn;
return 0;
}
团队作业 搜索
#include<bits/stdc++.h>
using namespace std;
int n,m,sum=0;
char a[21][21];
int zx[4]={1,-1,0,0};
int zy[4]={0,0,1,-1};
void dfs(int x,int y)
{
a[x][y]='#';
int dx,dy;
sum++;
for(int i=0;i<4;i++)
{
dx=x+zx[i];
dy=y+zy[i];
if(dx>=1&&dx<=m&&dy>=1&&dy<=n&&a[dx][dy]=='.')
{
dfs(dx,dy);
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
}
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(a[i][j]=='@')
{
dfs(i,j);
}
}
}
cout<<sum;
}
洛谷 P2036 [COCI2008-2009#2] PERKET
#include<bits/stdc++.h>
using namespace std;
int n,m,sum=0;
char a[21][21];
int zx[4]={1,-1,0,0};
int zy[4]={0,0,1,-1};
void dfs(int x,int y)
{
a[x][y]='#';
int dx,dy;
sum++;
for(int i=0;i<4;i++)
{
dx=x+zx[i];
dy=y+zy[i];
if(dx>=1&&dx<=m&&dy>=1&&dy<=n&&a[dx][dy]=='.')
{
dfs(dx,dy);
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
}
}
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(a[i][j]=='@')
{
dfs(i,j);
}
}
}
cout<<sum;
}
全排列问题
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[10];
int n,jiechen = 1;
cin >> n;
for(int i = 1 ; i <= n ; i++)
{
a[i] = n-i+1;
jiechen *= i;
}
for(int i = 1 ; i <= jiechen ; i++)
{
next_permutation(a+1,a+n+1);
for(int j = 1 ; j <= n ; j++)
cout<< " " << a[j];
cout << endl;
}
return 0;
}
迷宫
#include<iostream>
using namespace std;
int n,m,t;
int x1,y1,x2,y2;
int maze[6][6];
bool vis[6][6];
int sum=0;
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
int main()
{
bool in(int x,int y);
void dfs(int x,int y);
cin >> n >> m >> t;
cin >> x1 >> y1 >> x2 >> y2;
for(int i=0;i<t;i++)
{
int x,y;
cin >> x >> y;
maze[x][y]=1;
}
dfs(x1,y1);
cout<<sum<<endl;
return 0;
}
bool in(int x,int y)
{
return x>=1&&x<=n&&y>=1&&y<=m;
}
void dfs(int x,int y)
{
if(x==x2&&y==y2)
{
sum++;
}
vis[x][y]=1;
for(int i=0;i<4;i++)
{
int tx=x+dir[i][0];
int ty=y+dir[i][1];
if(in(tx,ty)&&maze[tx][ty]!=1&&!vis[tx][ty])
{
dfs(tx,ty);
}
}
vis[x][y]=0;
}
部分内容参考了一些大佬的想法。