前言:作为一名蒟蒻,我只能从简单的搜索题写起
搜索bfs
bfs 名字是广度优先搜索
核心思想就是我从一个节点出发,先遍历一遍距离为1的,再遍历距离为2的……
这个如果看不懂(就直接退役吧)当然还有别的办法:
上例题看代码!
马的遍历
我们先来看题意,就是看你的到达每一格需要的最少步数
那么我们想,我们可以让儿先走一步,然后看看走一步的那些点有哪些,让它们的ans[i][j]=已经走的步数,vis[i][j]=1 我们记录下刚才走到了哪里,然后接着上一步继续走,然后我们再让此时的ans[i][j]=已经走的步数,vis[i][j]=1,直到儿不能再往任何地方走了为止
int n,m,u,v;
queue <int> x,y;
int dx[8]={-2,-2,2,2,1,-1,1,-1};
int dy[8]={-1,1,-1,1,2,-2,-2,2};
int ans[410][410];
bool vis[410][410];
void bfs(){
while(!x.empty()){
int x1=x.front(),y1=y.front();
x.pop(),y.pop();
for(int i=0,x2,y2;i<8;i++){
x2=x1+dx[i],y2=y1+dy[i];
if(vis[x2][y2]||x2<1||y2<1||x2>n||y2>m) continue;
vis[x2][y2]=true;
// cout<<x2<<" "<<y2<<endl;
ans[x2][y2]=ans[x1][y1]+1;
x.push(x2),y.push(y2);
}
}
}
int main(){
// freopen("1.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n>>m>>u>>v;
memset(ans,-1,sizeof ans);
x.push(u),y.push(v);
vis[u][v]=1;
ans[u][v]=0;
bfs();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++) printf("%-5d",ans[i][j]);
printf("\n");
}//注意场宽!!
return 0;
}
这里就是代码了
广搜有几个技巧
1.用queue记录下当前的状态
2.不走回头路
3.遍历可以走的地方时用dx,dy表示,写一个循环
这就是广搜,应用主要集中在图论
spfa,dijkstra都会用到广搜
深搜
深搜就是一个非常重要的东西了,但是它确实很麻烦,dfs,学名深度优先搜索,简称就是一步搜到底
这个真的没什么可以讲的,只有在题里面才能体会的到
洛谷P1036 选数
一道经典的深度优先搜索题
题意就是n个数选m个,算一算它们的和是不是质数
质数筛之前的博客中写过,这里不再赘述
那这个问题我们应该如何解决呢?
我们发现,我们可以循环着去取数
但是选过的不能再选,所以我们的可以
void dfs(int now,int tot,int first)
三个变量分别表示 现在已经取了几个数,现在取得数的和,现在该取第first个数了
搜的边界显然是now== m时或者first==n时check(tot)
那么我们的代码也就自然而然的出来了
bool prime(int x){
if(x==1) return 0;
for(int i=2;i*i<=x;i++) if(x%i==0) return 0;
return 1;
}
void dfs(int now,int sum,int first){
if(now==k){
if(prime(sum)) ans++;
return;
}
for(int i=first;i<=n;i++){
if(!vis[i]){
vis[i]=true;
dfs(now+1,sum+a[i],i);
vis[i]=false;/*这里的vis变量处理是关键,可以好好理解一下*/
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
dfs(0,0,1);
cout<<ans;
}
理论来说搜索的知识并不多,但是难度和思想还是有的,多刷题,是学好搜索的必经之路