蓝桥杯第1022题 玩具蛇 基础DFS C++ Java

题目

思路和解题方法

  1. 问题理解:此题要求找出将一条由16节正方形构成的玩具蛇放入4x4的方格中的不同方式数。每节蛇可以是直线或直角转弯,且蛇的形状需要完全覆盖盒子里的16个格子,每个格子仅被蛇的一个部分占据。

  2. 状态表示 :使用一个二维数组st[4][4]来标记每个格子是否被蛇占用(0表示未占用,1表示占用)。同时,使用深度优先搜索(DFS)来探索所有可能的放置方式。

  3. DFS策略

    • 参数定义dfs(x, y, len)函数中,xy表示当前蛇头的位置坐标,len表示当前已经放置蛇的节段数目。
    • 递归终止条件 :当len达到16时,说明蛇的所有部分都已放置完毕,方案数加1。
    • 边界判断与重复检查:每次尝试移动前,先检查新位置是否在边界内以及是否已访问过。
    • 移动方向:对于当前位置,尝试向上、下、左、右四个方向移动,每次移动后递归调用自身,探索新的路径。
    • 回溯:在每个方向探索结束后,需要恢复现场,即撤销当前位置的占用标记,以允许探索其他路径。
  4. 代码实现

    • 首先遍历所有可能的起始位置,对每个起始位置调用dfs函数。
    • dfs函数中,进行上述逻辑处理,包括移动、计数、回溯等操作。

c++ 代码

cpp 复制代码
#include <iostream>
using namespace std;

// 方向数组,dx表示行变化,dy表示列变化,分别对应上、下、左、右四个方向
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, -1, 0, 1};

// st数组用来标记网格中的每个格子是否已经被蛇占用过
int st[4][4];      

// res用于记录可以成功放置玩具蛇的总方案数
int res = 0;       

// 深度优先搜索函数,探索放置蛇的路径
void dfs(int x, int y, int len) {
    // 如果当前位置超出网格范围,则返回
    if (x < 0 || y < 0 || x >= 4 || y >= 4) {
        return;  
    }
    // 如果当前位置已经走过,则返回,避免重复路径
    if (st[x][y] == 1) {
        return;  
    }
    // 如果蛇的长度已经达到15(即全部摆放完毕),方案数加一并返回
    if (len == 15) {
        res++;   
        return;
    }

    // 标记当前位置已被占用
    st[x][y] = 1;  
    // 依次尝试向上、下、左、右四个方向进行下一步探索
    for (int i = 0; i < 4; i++) {
        dfs(x + dx[i], y + dy[i], len + 1);  
    }
    // 回溯:恢复当前位置为未访问状态,以便进行其他路径的探索
    st[x][y] = 0;  
}

// 主函数
int main() {
    // 遍历网格的每一个起点,启动深度优先搜索寻找所有可能的蛇形路径
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            dfs(i, j, 0);
        }
    }
    // 输出所有可行的蛇形路径总数
    cout << res << endl;  
    return 0;
}

Java 版本(仅供参考)

java 复制代码
import java.util.Arrays;

public class Main {
    static int[][] st = new int[4][4];      
    static int res = 0;       
    static int[][] dx_dy = {{-1, 0, 1, 0}, {0, -1, 0, 1}};  

    public static void dfs(int x, int y, int len) {
        if (x < 0 || y < 0 || x >= 4 || y >= 4) {
            return;  
        }
        if (st[x][y] == 1) {
            return;  
        }
        if (len == 15) {
            res++;   
            return;
        }

        st[x][y] = 1;  
        for (int i = 0; i < 4; i++) {
            dfs(x + dx_dy[0][i], y + dx_dy[1][i], len + 1);  
        }
        st[x][y] = 0;  
    }

    public static void main(String[] args) {
        Arrays.stream(st).forEach(row -> Arrays.fill(row, 0)); // 初始化st数组
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                dfs(i, j, 0);
            }
        }
        System.out.println(res);  
    }
}

Python 版本(仅供参考)

python 复制代码
def dfs(x, y, len):
    if x < 0 or y < 0 or x >= 4 or y >= 4:
        return
    if st[x][y] == 1:
        return
    if len == 15:
        global res
        res += 1
        return

    st[x][y] = 1
    for i in range(4):
        dfs(x + dx[i], y + dy[i], len + 1)
    st[x][y] = 0

dx, dy = [-1, 0, 1, 0], [0, -1, 0, 1]
st = [[0]*4 for _ in range(4)]
res = 0

for i in range(4):
    for j in range(4):
        dfs(i, j, 0)

print(res)

代码细节:

  • 递归函数dfs(x, y, len)负责实际的搜索过程,其中(x, y)是当前探索的位置,len表示已经探索了多少个格子(即蛇的长度)。
  • 边界检查:在尝试移动到新位置之前,先检查新位置是否还在网格范围内,防止越界。
  • 重复检查 :通过st数组避免重复访问同一格子,提高搜索效率,减少无效分支。
  • 递归终止条件 :当蛇的长度达到16时,说明找到了一个完整的解决方案,累加结果计数器res
  • 回溯:在递归返回前,撤销当前位置的占用标记,以便于从当前节点出发探索其他路径。
  • 全面搜索:通过外层循环遍历所有可能的起始点,确保从每个格子出发都尝试寻找解。

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦 >人< 。

相关推荐
公贵买其鹿2 分钟前
List深拷贝后,数据还是被串改
java
xlsw_3 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹4 小时前
基于java的改良版超级玛丽小游戏
java
唐诺4 小时前
几种广泛使用的 C++ 编译器
c++·编译器
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭4 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫5 小时前
泛型(2)
java
超爱吃士力架5 小时前
邀请逻辑
java·linux·后端
南宫生5 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石5 小时前
12/21java基础
java
不想当程序猿_5 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯