王道论坛机试指南学习笔记(五)搜索

1. 枚举

- 简述

  • 尝试搜索空间内所有可能的解
  • 搜索空间越大,使用枚举进行搜索的复杂度就越高

- 百鸡问题

  • 题目:用小于等于 n 元去买 100 只鸡,大鸡 5 元/只,小鸡 3 元/只,还有 1/3 元每只的一种小鸡,分别记为 x 只,y 只,z 只。编程求解 x,y,z 所有可能解。

  • 解决方式:暴力枚举

  • 方法:

    public static void HundredChicks(int sum){
         
         
      for (int i = 0; i <= 100; i++) {
         
         
        for (int j = 0; j <= 100-i; j++) {
         
         
          int z = 100 -i -j;
          // 采用对不等式两端所有数字都乘3的操作,避免除法带来的精度损失
          if(i*5*3+j*3*3+z < sum*3)
            System.out.println("x="+i+", y="+j+", z="+z);
        }
      }
    }
    
  • 总结:在复杂度允许的范围内,直白的枚举思路简单,代码清晰,所以在一些看似无从下手的题目面前,我们要换个角度,试着从更暴力的角度去思考

2.2 BFS

- 算法

  • 问题的解空间内有若干可能的状态,每一次状态迁移都从这些可能状态中选择一个执行;

  • 包含搜索空间中所有状态的树:解答树

    • 所谓广度优先搜索,即在遍历解答树时使每次状态转移时扩展出尽可能多的新状态,并且按照各个状态出现的先后顺序依次扩展它们。
      在这里插入图片描述
  • 剪枝:

    • 剪去解答树中不可能是我们所需答案的子树,减少所有范围,提高搜索效率;
  • 使用队列实现:

    • 将每次扩展得到的新状态放入队列中;
    • 只有排在该状态之前的所有状态都被扩展完成,才对此状态进行扩展;
  • 使用标记数组:

    • 为防止对无效状态的重复搜索,增加标记数组;
    • 当已经访问过一个状态后,将其状态在标记数组中对应的位置进行标记(true/false)

- 迷宫问题

  • 题目简述:

Ignatius 被魔王抓走了,有一天魔王出差去了,这可是 Ignatius 逃亡的好机会. 魔王住在一个城堡里,城堡是一个 ABC 的立方体,可以被表示成 A 个 B*C 的矩 阵,刚开始 Ignatius 被关在(0,0,0)的位置,离开城堡的门在(A-1,B-1,C-1)的位置,现 在知道魔王将在 T 分钟后回到城堡,Ignatius 每分钟能从一个坐标走到相邻的六个 坐标中的其中一个.现在给你城堡的地图,请你计算出 Ignatius 能否在魔王回来前 离开城堡(只要走到出口就算离开城堡,如果走到出口的时候魔王刚好回来也算逃 亡成功),如果可以请输出需要多少分钟才能离开,如果不能则输出-1。

在这里插入图片描述

  • 三维迷宫,从 {0,0,0} 出发,到达对角线出口即为胜利;
  • 迷宫中 1 表示墙,0 表示路;
static boolean[][][] mark;
static int[][][] maze = {
   
   {
   
   {
   
   0,1,1,1}, {
   
   0,0,1,1}, {
   
   0,1,1,1}}, {
   
   {
   
   1,1,1,1}, {
   
   1,0,0,1}, {
   
   0,1,1,1}}, {
   
   {
   
   0,0,0,0}, {
   
   0,1,1,0}, {
   
   0,1,1,0}}};
static int[][] options = {
   
   {
   
   1,0,0}, {
   
   -1,0,0}, {
   
   0,1,0}, {
   
   0,-1,0}, {
   
   0,0,1}, {
   
   0,0,-1}};
static Queue<Cell> queue = new LinkedList<>();

static int BFS(int a, int b, int c){
   
   
    while (!queue.isEmpty()){
   
   
        Cell cell = queue.poll();
        int x = cell.x, y = cell.y, z = cell.z;
        for (int i = 0; i < options.length; i++) {
   
   
            x = cell.x + options[i][0];
            y = cell.y + options[i][1];
            z = cell.z + options[i][2];
            //排除特殊情况,当前前进目标不在迷宫内、当前位置已访问或当前位置是墙,则跳过该位置
            if ( x<0 || x>a-1 || y<0 || y>b-1 || z<0 || z>c-1) continue;
            if (mark[x][y][z]) continue;
            if (maze[x][y][z]==1) continue;
            Cell new_cell = new Cell(x, y, z, cell.time+1);
            queue.offer(new_cell);
            mark[x][y][z] = true;
            if(x==a-1&&y==b-1&&z==c-1) return ne
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值