1.基本DFS
#include <bits/stdc++.h>
using namespace std;
int n;
int path[10];//记录每个位置上的数字是几
int st[10];
void dfs(int u)//u表示当前层数
{
if(u==n)//u恰好走到最后一层
{
for(int i=0;i<n;i++) printf("%d ",path[i]);
puts("");
return;
}
for(int i=1;i<=n;i++)//看看哪个数字没被用过
{
if (!st[i])
{
path[u]=i;//把枚举的这个放在当前层
st[i]=1;
dfs(u+1);
st[i]=0;
}
}
}
int main()
{
cin>>n;
dfs(0);
return 0;
}
n皇后问题
#include <bits/stdc++.h>
using namespace std;
const int N=20;
int n;
int col[N],dx[N],dy[N];
char g[N][N];
void dfs(int u)
{
if(u==n)
{
for(int i=0;i<n;i++) puts(g[i]);
puts("");
return;
}
for(int i=0;i<n;i++)
{
if(!col[i]&&!dx[u+i]&&!dy[n+i-u])
{
g[u][i]='Q';
col[i]=dx[i+u]=dy[i+n-u]=1;
dfs(u+1);
col[i]=dx[i+u]=dy[i+n-u]=0;
g[u][i]='.';
}
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
g[i][j]='.';
dfs(0);
return 0;
}
2.bfs 八数码问题
#include <bits/stdc++.h>
using namespace std;
int bfs(string state)
{
queue<string> q;
unordered_map<string,int> d;//从第一个状态到当前状态的距离
q.push(state);
d[state]=0;
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
string end="12345678x";
while(q.size())
{
auto t=q.front();
q.pop();
if(t==end) return d[t];
int distance=d[t];
int k=t.find('x');//找到x在一维数组中的位置
int x=k/3,y=k%3;//x,y存储'x'对应的二维数组中的位置
for(int i=0;i<4;i++)
{
int a=x+dx[i],b=y+dy[i];//下一个位置的坐标
if(a>=0&&a<3&&b>=0&&b<3)//下一个位置没有出界
{
swap(t[a*3+b],t[k]);//把x块移动到下一个位置
if(!d.count(t))//如果新状态没有出现过
{
d[t]=distance+1;
q.push(t);
}
swap(t[a*3+b],t[k]);//恢复现场,重新交换t串中对应位置的元素
}
}
}
return -1;
}
int main()
{
string state;
char c;
for(int i=0;i<9;i++)
{
cin>>c;
state+=c;
}
cout<<bfs(state)<<endl;
return 0;
}
走迷宫
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int>PII;
const int N=110;
int n,m;
int g[N][N],d[N][N];
int bfs()
{
queue<PII> q;
memset(d,-1,sizeof(d));//标记地图上每一个点都没走过
//数组下标从0开始
d[0][0]=0;//先站在第一个点的位置,移动的次数为0
q.push({0,0});//并入队
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};//拓展点
while(q.size())
{
auto t=q.front();
q.pop();
for(int i=0;i<4;i++)//遍历取出的队头元素的四个方向
{
int x=t.first+dx[i],y=t.second+dy[i];
if(x>=0&&x<n&&y>=0&&y<m&&d[x][y]==-1&&g[x][y]==0)
{
d[x][y]=d[t.first][t.second]+1;//从(0,0)到(x,y)点的移动次数
q.push({x,y});
}
}
}
return d[n-1][m-1];
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
scanf("%d",&g[i][j]);
printf("%d\n",bfs());
return 0;
}
1101. 献给阿尔吉侬的花束
#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int,int>PII;
const int N=210;
int n,m;
char g[N][N];
int dist[N][N];
int bfs(PII start,PII end)
{
queue<PII> q;
memset(dist,-1,sizeof dist);
dist[start.x][start.y]=0;
q.push(start);
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
while(q.size())
{
auto t=q.front();
q.pop();
for(int i=0;i<4;i++)
{
int x=t.x+dx[i],y=t.y+dy[i];
if(x<0||x>=n||y<0||y>=m) continue;//出界
if(g[x][y]=='#') continue;//障碍物
if(dist[x][y]!=-1) continue;//之前已经遍历过了
dist[x][y]=dist[t.x][t.y]+1;
if(end==make_pair(x,y)) return dist[x][y];
q.push({x,y});
}
}
return -1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%s",g[i]);
PII start,end;
for(int i=0;i<n;i++)//找到起点和终点
for(int j=0;j<m;j++)
if(g[i][j]=='S') start={i,j};
else if(g[i][j]=='E') end={i,j};
int distance=bfs(start,end);
if(distance==-1) puts("oop!");
else printf("%d\n",distance);
}
return 0;
}
1113.红与黑【dfs迷宫搜索】
#include <bits/stdc++.h>
using namespace std;
const int N=25;
int n,m;
char g[N][N];
bool st[N][N];
int dx[4]= {-1,0,1,0},dy[4]= {0,1,0,-1};
int dfs(int x,int y)
{
int cnt=1;
st[x][y]=true;
for(int i=0; i<4; i++)
{
int a=x+dx[i],b=dy[i]+y;
if(a<0||a>=n||b<0||b>=m)
continue;
if(g[a][b]!='.')
continue;//不是黑色不能走
if(st[a][b])
continue;//周过一次不能再走
cnt+=dfs(a,b);//可以走
}
return cnt;
}
int main()
{
while(cin>>m>>n,n||m)
{
for(int i=0; i<n; i++)
cin>>g[i];//输入地图
int x,y;
//查找起点
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
if(g[i][j]=='@')
{
x=i;
y=j;
}
memset(st,0,sizeof st);
cout<<dfs(x,y)<<endl;
}
return 0;
}
1096. 地牢大师——三维bfs搜索
【三位版献给阿尔吉侬的花束】
#include <bits/stdc++.h>
using namespace std;
const int N=110;
struct Point
{
int x,y,z;
};
int L,R,C;
char g[N][N][N];
Point q[N*N*N];
int dist[N][N][N];
int dx[6]={1,-1,0,0,0,0};
int dy[6]={0,0,1,-1,0,0};
int dz[6]={0,0,0,0,1,-1};
int bfs(Point start, Point end)
{
int hh=0,tt=0;
q[0]=start;
memset(dist,-1,sizeof dist);
dist[start.x][start.y][start.z]=0;
while(hh<=tt)
{
auto t=q[hh++];
for(int i=0;i<6;i++)
{
int x=t.x+dx[i],y=t.y+dy[i],z=t.z+dz[i];
if(x<0||x>=L||y<0||y>=R||z<0||z>=C) continue;
if(g[x][y][z]=='#') continue;
if(dist[x][y][z]!=-1) continue;
dist[x][y][z]=dist[t.x][t.y][t.z]+1;
if(x==end.x&&y==end.y&&z==end.z) return dist[x][y][z];
q[++tt]={x,y,z};
}
}
return -1;
}
int main()
{
while(scanf("%d%d%d",&L,&R,&C),L||R||C)
{
Point start,end;
for(int i=0;i<L;i++)
for(int j=0;j<R;j++)
{
scanf("%s",g[i][j]);
for(int k=0;k<C;k++)
{
char c=g[i][j][k];
if(c=='S') start={i,j,k};
else if(c=='E') end={i,j,k};
}
}
int distance=bfs(start,end);
if(distance==-1) puts("Trapped!");
else printf("Escaped in %d minute(s).\n",distance);
}
return 0;
}
1233. 全球变暖
连通块搜索,bfs简单应用
#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair <int,int >PII;
const int N=1010;
int n;
char g[N][N];
bool st[N][N];
PII q[N*N];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
void bfs(int sx,int sy,int &total,int &bound)
{
int hh=0,tt=0;
q[0]={sx,sy};
st[sx][sy]=true;
while(hh<=tt)
{
PII t=q[hh++];
total++;
bool is_bound=false;
for(int i=0;i<4;i++)
{
int x=t.x+dx[i],y=t.y+dy[i];
if(x<0||x>=n||y<0||y>=n) continue;
if(st[x][y]) continue;
if(g[x][y]=='.')
{
is_bound=true;
continue;
}
q[++tt]={x,y};
st[x][y]=true;
}
if(is_bound) bound++;
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%s",g[i]);
int cnt=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(!st[i][j]&&g[i][j]=='#')//判断每个连通块
{
int total=0,bound=0;
bfs(i,j,total,bound);
if(total==bound) cnt++;
}
printf("%d\n",cnt);
return 0;
}
1207. 大臣的旅费
树的直径:一棵树里面长度最长的路径
求法:
①任取一点x:求出各点到x的距离dist[x]
②找到距离x最远的点y, 再反相求一次dist[y]
③dist[y]的最大值是树的直径
tips:路费转化成公式
#include <bits/stdc++.h>
using namespace std;
const int N=100010;
int n;
struct Edge
{
int id,w;
};
vector<Edge> h[N];
int dist[N];
void dfs(int u,int father,int distance)
{
dist[u]=distance;
for(auto node:h[u])
if(node.id!=father) //不能往回走
dfs(node.id,u,distance+node.w);
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n-1;i++)//n个点n-1条边
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);//双向边
h[a].push_back({b,c});
h[b].push_back({a,c});
}
dfs(1,-1,0);
int u=1;
for(int i=1;i<=n;i++)
if(dist[i]>dist[u])
u=i;
dfs(u,-1,0);
for(int i=1;i<=n;i++)
if(dist[i]>dist[u])
u=i;
int s=dist[u];
printf("%lld\n",s*10+s*(s+1ll)/2);
return 0;
}