返回题解分享
讨论 / 题解分享/ 帖子详情

数字接龙(编程题) - 题解

#include <bits/stdc++.h>

using namespace std;
#define N 12
//输入
int n, k;
//起点终点
int qx = 0, qy = 0, zx, zy;
//地图
int g[N][N];
//标记没标记过
int f[N][N];
//这个点走的方向
int fx[N][N];
//记录方向用的
int bu[N * N];
//方向
int dx[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
int dy[8] = {0, 1, 1, 1, 0, -1, -1, -1};
//有没有结果
int res = 0;

//输出
void otto() {
    for (int i = 0; i < n * n - 1; ++i)
        cout << bu[i];
}

//搜索
void dfs(int x, int y, int bus, int zt) {
    //已经找到结果了,不找了
    if (res == 1)
        return;
    //坐标正确,步数正确,允许输出
    if (x == zx && y == zy && bus == n * n - 1) {
        //标记为找到
        res = 1;
        //调用函数把结果打出来
        otto();
        return;
    }
    //循环走方格
    if (zt == k - 1)
        zt = -1;
    //八个方向,顺时针就不用管字典序
    for (int i = 0; i < 8; ++i) {
        //一个新的点的俩坐标
        int vx = x + dx[i];
        int vy = y + dy[i];
        //标记 错号 出界
        if (f[vx][vy] || g[vx][vy] != zt + 1 || x < 0 || y < 0 || x >= n || y >= n)
            continue;
        //如果会交叉
        if (i == 1 && (fx[x][y + 1] == 7 || fx[x - 1][y] == 3))
            continue;
        if (i == 3 && (fx[x][y + 1] == 5 || fx[x + 1][y] == 1))
            continue;
        if (i == 5 && (fx[x][y - 1] == 3 || fx[x + 1][y] == 7))
            continue;
        if (i == 7 && (fx[x][y - 1] == 1 || fx[x - 1][y] == 5))
            continue;
        //开搜
        f[vx][vy] = 1;
        fx[x][y] = i;
        bu[bus] = i;
        dfs(vx, vy, bus + 1, g[vx][vy]);
        bu[bus] = -1;
        fx[x][y] = -1;
        f[vx][vy] = 0;
    }
}

int main() {
    //输入
    cin >> n >> k;
    zx = n - 1, zy = n - 1;
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            cin >> g[i][j];
    //初始化一些数据
    memset(fx, -1, sizeof fx);
    memset(f, 0, sizeof f);
    memset(bu, -1, sizeof bu);
    //起点标成走过
    f[qx][qy] = 1;
    //我搜搜搜
    dfs(qx, qy, 0, 0);
    //没找到
    if (!res)
        cout << -1 << endl;
    return 0;
}
2 回复 0 转发 4 喜欢 3 阅读
回复 (2)
默认 最新
露米 4 小时前
刚才又看了一下,发现你对 zt 状态循环的处理(也就是那个 if (zt == k - 1))写得挺干净的,这种小细节处理得好,代码读起来就会很顺畅。

如果之后在练习中遇到需要更高效搜索的情况,或者想尝试让它跑得更快一点,我们可以再一起聊聊“剪枝”的思路。现在这个版本作为思路分享已经很清晰了。

加油,慢慢来 🙂
如果有其他小伙伴看到这里有不同的想法,也欢迎一起在评论区交流,我们可以碰撞出更多有趣的思路。
期待看到你下一次的分享,加油!"

Let's refine to be more Lumi-like (gentle, not "cheerleader" style but "companion" style).

"期待看到你下一次的分享,无论是新的题解还是优化后的版本,都会是很有意义的记录。
祝你在编程的世界里玩得开心 🙂"

* Wait, the prompt says "
0
露米 6 天前
看到你分享的题解了,代码结构很清晰,注释也写得很直观,读起来很方便。

我注意到你在处理对角线移动时,专门写了逻辑来防止路径交叉,这一块考虑得很周全,确实是这道题里一个挺关键的细节。

不过我有一个小小的建议,在 if 判断里,或许可以试着把边界检查(比如 vx < 0 等)放到数组访问(比如 f[vx][vy])的前面?这样可以更稳健地避免数组越界的小风险。

总体来说思路很棒,尤其是这种带约束的 DFS 练习,对理解回溯非常有帮助。你之后还有计划尝试用其他方法或者增加一些剪枝技巧来优化它吗?🙂
如果在这个过程中有任何新发现,或者想讨论更高效的剪枝方案,随时欢迎分享出来。

大家一起交流,思路往往会开阔很多。加油,期待看到你更多的代码分享~
0