搜索二
复健
注:这一篇笔记里的搜索题都非常简单
搜索二
迷宫
https://www.luogu.com.cn/problem/P1605
不要忘了回溯
#include<iostream>
#include<cstdio>
#include<algorithm>
#define maxn 10
using namespace std;
int mg[maxn][maxn];
int ans;
int dirx[4]={1,-1,0,0};
int diry[4]={0,0,1,-1};
int sx,sy,tx,ty;
int n,m,t;
void dfs(int x,int y)
{
if(x==tx&&y==ty)
{
ans++;
return;
}
for(int i=0;i<4;i++)
{
int nx=x+dirx[i];
int ny=y+diry[i];
if(mg[nx][ny]==1&&nx>=1&&nx<=n&&ny>=1&&ny<=m)
{
mg[nx][ny]=-1;
dfs(nx,ny);
mg[nx][ny]=1;
}
}
}
int main()
{
cin>>n>>m>>t;
cin>>sx>>sy>>tx>>ty;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++) mg[i][j]=1;
}
for(int i=1;i<=t;i++)
{
int x,y;
cin>>x>>y;
mg[x][y]=-1;
}
mg[sx][sy]=-1;
dfs(sx,sy);
printf("%d\n",ans);
return 0;
}
这道题有个非常重要的点:我们要把起点设为不能访问,如果不这样的话,我们可能会走过起点两次,这样你的答案就会多于正确答案
跳马
https://www.luogu.com.cn/problem/P1644
因为一直是往右的,所以我们不需要写回溯(因为不会跳到原来走过的点)
#include<iostream>
#include<cstdio>
#include<algorithm>
#define maxn 20
using namespace std;
int ans;
int dirx[4]={1,2,2,1};
int diry[4]={2,1,-1,-2};
int n,m;
void dfs(int x,int y)
{
if(x==m&&y==n)
{
ans++;
return;
}
for(int i=0;i<4;i++)
{
int nx=x+dirx[i];
int ny=y+diry[i];
if(nx>=0&&nx<=m&&ny>=0&&ny<=n)
{
dfs(nx,ny);
}
}
}
int main()
{
cin>>n>>m;
dfs(0,0);
printf("%d\n",ans);
return 0;
}
八皇后问题
https://www.luogu.com.cn/problem/P1219
注意因为我们用到了,所以我们的数组要开大一点
#include<iostream>
#include<cstdio>
#include<algorithm>
#define maxn 30
using namespace std;
int ansnum;
int ans[5][maxn];
int row[maxn];
int col[maxn],L[maxn],R[maxn];//左对角线y-x+13,右对角线y+x
int n;
void dfs(int x)
{
if(x==n+1)
{
ansnum++;
if(ansnum<=3)
{
for(int i=1;i<=n;i++) ans[ansnum][i]=row[i];
}
return;
}
for(int i=1;i<=n;i++)
{
if(!col[i]&&!L[i-x+13]&&!R[i+x])
{
col[i]=1;
L[i-x+13]=1;
R[i+x]=1;
row[x]=i;
dfs(x+1);
col[i]=0;
L[i-x+13]=0;
R[i+x]=0;
}
}
}
int main()
{
cin>>n;
dfs(1);
for(int i=1;i<=3;i++)
{
for(int j=1;j<=n;j++) printf("%d ",ans[i][j]);
printf("\n");
}
printf("%d\n",ansnum);
return 0;
}
水坑计数(连通性问题)
https://www.luogu.com.cn/problem/P1596
第一种方法:
#include<iostream>
#include<cstdio>
#include<algorithm>
#define maxn 110
using namespace std;
char mg[maxn][maxn];
int n,m;
int dx[8]={-1,-1,-1,0,1,1,1,0};
int dy[8]={-1,0,1,1,1,0,-1,-1};
void dfs(int x,int y)
{
mg[x][y]='.';
for(int i=0;i<8;i++)
{
int tx=x+dx[i],ty=y+dy[i];
if(mg[tx][ty]=='W') dfs(tx,ty);
}
}
int main()
{
cin>>n>>m;
int ans=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++) cin>>mg[i][j];
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(mg[i][j]=='W')
{
ans++;
dfs(i,j);
}
}
}
printf("%d\n",ans);
return 0;
}
第二种方法:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#define maxn 110
using namespace std;
char mg[maxn][maxn];
int n,m;
int dx[8]={-1,-1,-1,0,1,1,1,0};
int dy[8]={-1,0,1,1,1,0,-1,-1};
void bfs(int x,int y)
{
queue<pair<int,int> > q;
q.push({x,y});
mg[x][y]='.';
while(!q.empty())
{
pair<int,int> x=q.front();
q.pop();
for(int i=0;i<8;i++)
{
int a=x.first+dx[i],b=x.second+dy[i];
if(mg[a][b]=='W')
{
mg[a][b]='.';
q.push({a,b});
}
}
}
}
int main()
{
cin>>n>>m;
int ans=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++) cin>>mg[i][j];
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(mg[i][j]=='W')
{
ans++;
bfs(i,j);
}
}
}
printf("%d\n",ans);
return 0;
}
矩阵距离
给定一个行列的矩阵,和之间的曼哈顿距离为
输出为一个行列的证书矩阵你,其满足
思路:洪水从多个源点,每秒扩展一步,先到哪个点,哪个点就确定最小距离
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 15
using namespace std;
char g[maxn][maxn];
int dis[maxn][maxn];
int dx[4]={0,0,-1,1};
int dy[4]={-1,1,0,0};
int n,m;
struct Node
{
int x,y;
};
void bfs()
{
memset(dis,-1,sizeof(dis));
queue<Node> q;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(g[i][j]=='1')
{
dis[i][j]=0;
q.push({i,j});
}
}
}
while(!q.empty())
{
Node u=q.front();
q.pop();
int x=u.x,y=u.y;
for(int i=0;i<4;i++)
{
int tx=x+dx[i],ty=y+dy[i];
if(tx<0||tx>=n||ty<0||ty>=m) continue;
if(dis[tx][ty]!=-1) continue;
dis[tx][ty]=dis[x][y]+1;
q.push({tx,ty});
}
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++) cin>>g[i][j];
}
bfs();
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++) printf("%d ",dis[i][j]);
printf("\n");
}
return 0;
}
八数码难题
https://www.luogu.com.cn/problem/P1379
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<unordered_map>
#define maxn 10
using namespace std;
unordered_map<string,int> d;
queue<string> q;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int bfs(string str)
{
q.push(str);
string end="123804765";;
while(q.size())
{
string s=q.front();
q.pop();
if(s==end) return d[s];
int k=s.find('0');
int x=k/3,y=k%3;//下标位置的转换
for(int i=0;i<4;i++)
{
int tx=x+dx[i],ty=y+dy[i];
if(tx<0||tx>=3||ty<0||ty>=3) continue;
int dis=d[s];
swap(s[k],s[tx*3+ty]);
if(!d.count(s)) d[s]=dis+1,q.push(s);
swap(s[k],s[tx*3+ty]);
}
}
}
int main()
{
string s;
cin>>s;
printf("%d\n",bfs(s));
return 0;
}
正因无所有,才会无所畏
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现