搜索 算法

一.深度优先搜索(DFS)

1.基本概念

  深度优先搜索是一种枚举所有完整路径以遍历所有情况的搜索方法。
  沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。

2.基本模板

递归实现:

void dfs(int k)
{ //k代表递归层数,或者说要填第几个空
  if(所有空已经填完了)
 {   判断最优解/记录答案;
  return; }
 for(枚举这个空能填的选项)
  if(这个选项是合法的)
{  记录下这个空(保存现场);
  dfs(k+1);
 取消这个空(恢复现场);
 }
}

3.问题示例

四阶数独
1.题目描述

 四阶数独。给出一个4x4的格子,每个格子只能填写1到4的整数,要求每行、每列和四等分更小的正方形部分都刚好由1到4组成。
 给出空白的格子,请问:一共有多少种合法的填写方法?

2.代码

#include <iostream>
using namespace std;
#define size 5
int n=4*4,t=0,a[size*size];
int b1[size][5],b2[size][5],b3[size][5];//三个数组分别记录行,列,四小格
void dfs(int x)
{  if(x>n)  //空填满则输出
 { t++;
   for(int i=1;i<=n;i++)
  {cout<<a[i]<<" ";
   if(i%4==0) cout<<endl;}
   cout<<endl;
   return;
 }
   int row=(x-1)/4+1;  //行的编号
   int col=(x-1)%4+1;  //列的编号
   int block=(row-1)/2*2+(col-1)/2+1;  //四小格的编号
   for(int i=1;i<=4;i++)
    if(b1[row][i]==0&&b2[col][i]==0&&b3[block][i]==0)
     {a[x]=i;
      b1[row][i]=1;b2[col][i]=1;b3[block][i]=1;  //标记位置
      dfs(x+1);   //下一层递归
      b1[row][i]=0;b2[col][i]=0;b3[block][i]=0;  //取消标记
     }
}
int main()
{ dfs(1);
  cout<<t;
  return 0;
}

二.广度优先搜索(BFS)

1.基本概念

 广度优先搜索算法是一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。
 在需要解决连通性,最短路问题时,可以考虑使用广度优先搜索。

2.基本模板

Q.push(初始状态); //将初始状态入队
while(!Q.empty())
{ State u=Q.front(); //取出队首
  Q.pop();  //出队
 for(枚举所有可扩展状态)  //找到u的所有可达状态v
 if(是合法的)  //v需要满足某些条件,如未访问过、未在队内等
 Q.push(v);  //入队(同时可能需要维护某些必要信息)
}

3.问题示例

1.问题描述

有一个n x m 的棋盘,在某个点 (x, y)上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。

2.代码

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
#define N 310
struct coord
{ int x,y;
};
queue<coord> Q;
int a[N][N];
int b[8][2]={{2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2},{1,-2},{2,-1}};//马能走的8个方向
int main()
{ int m,n,sx,sy;
  memset(a,-1,sizeof(a));
  cin>>m>>n>>sx>>sy;
  coord t={sx,sy};
  Q.push(t);
  a[sx][sy]=0;
  while(!Q.empty())
  { coord c=Q.front();
    int cx=c.x,cy=c.y;
    Q.pop();
    for(int k=0;k<8;k++)
    {int x=cx+b[k][0],y=cy+b[k][1];
     int d=a[cx][cy];
     if(x<1||x>n||y<1||y>m||a[x][y]!=-1) continue;
     a[x][y]=d+1;
     coord t={x,y};
     Q.push(t);
    }
  }
  for(int i=1;i<=n;i++,puts(" "))
   for(int j=1;j<=m;j++)
    printf("%-5d",a[i][j]);
  return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值