蓝桥杯真题【路径之谜】

蓝桥杯真题【路径之谜】

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    public static void main(String[] args) {
      /*
      思路:
      本题涉及dfs+回溯+剪枝,解法可以参考:
      https://blog.dotcpp.com/a/83079

      关于dfs+回溯+剪枝的模板,参考:
      (dfs剪枝策略)https://blog.csdn.net/qq_38790716/article/details/88051412
      https://blog.csdn.net/yanweiqi1754989931/article/details/109603384
     (dfs+回溯+剪枝相关题目) https://blog.csdn.net/weixin_42072280/article/details/104580012
     https://blog.csdn.net/qq_38790716/article/details/88047900

     dfs模板框架:
     function dfs(当前状态){
        if(当前状态 == 目的状态){
              ···
          }
          for(···寻找新状态){
              if(状态合法){
                  vis[访问该点];
                  dfs(新状态);
                  ?是否需要恢复现场->vis[恢复访问]
              } 
          }
          if(找不到新状态){
              ···
          }
      }

      本题思路:
      1、所需数据结构:
      (1)两个存储自西向东、自北向南的靶数,相当于哈希表。
      (2)一个二维数组存储格子标记路径是否访问过(1到n),相当于visit数组。
      (3)一个数组当作栈存储走过的路径。
      (4)两个数组分别存x和y坐标的方向坐标,用于引导路径自某点下左上右的移动。
      (5)一个二维数组存储格子的数字标记。
      2、代码结构:
      function check(){
        // 因为在所有可能从起点到终点的路径中,只有满足靶数的那条,它在dfs遍历后靶数数组会一直减到为0
        检查两个靶数数组的元素是否都为0;
      }

      function dfs(x,y,step){
        //剪枝,即如果某个结点不满足条件,那么它后面的子树一定都无法达到,相当于串行
        if(剪枝条件:如果(x,y)的横向或纵向对应的靶数小于0,那么没必要继续走下去了){
          return
        }
        //当前状态 == 目的状态,即dfs截止条件
        if(终止条件:(x,y)是最后一个格子){
          if(检查从西向东、从北向南的靶数是否都正确,即check()){
            如果都满足两个数组的靶数,那么将栈中记录的格子都输出,就是正确走过的路径;
          }
        }
        for((x,y)四个方向都试着走一遍){
          用1、的(2)数组更新下一个方向(走下一步)的(x,y)坐标;
          if(合法条件:如果下个格子未被访问,且下一步的(x,y)没有查出格子边界){
            visit数组标记对下一步的格子(x,y)访问过;
            栈存储下一步的格子(x,y);
            对应下一步的格子(x,y)的靶数减1,用于控制路径朝向正确的方向;
            dfs(对下一步的格子继续四个方向的尝试)
            如果跳出了上面的dfs,说明不满足终止条件,那么此次尝试的方向不对,需要回溯,把记录靶数的数组、栈恢复原来状态;
            visit数组对此方向下一步的格子(x,y)恢复访问状态;
          }
        }
      }

      function main(){
        初始化靶数数组;格子标记数组;
        取(0,0)坐标进入栈中,visit[0][0]置1表示访问过;
        (0,0)横向和纵向的两个靶数减1;
        dfs(0,0,1) //从(0,0)位置开始走;
        return 0;
      }

      */
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        scan.close();
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值