首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

跳马问题:半张象棋盘上马的走法计数(递归回溯)

     編輯:關於C語言

问题描述

在 8×4 的半张中国象棋棋盘上(坐标 (0,0) 到 (8,4)),马从左下角 (0,0) 跳到右上角 (8,4)。马走“日”字:(+1,+2), (+2,+1), (+2,-1), (+1,-2) 四种相对移动(仅向右/上/下,不向左)。求不同路径总数。

建模与递推

设 f(x, y) 为从 (x,y) 跳到目标 (8,4) 的路径数。
递推:f(x,y) = Σ f(x+dx[i], y+dy[i]),四个方向均在棋盘内。
边界:f(8,4) = 1;越界返回 0。
由于无环(x 单调递增),可直接 DFS + 备忘录,或自底向上 DP。

C 语言实现(DFS + 备忘录)

#include <stdio.h>
#include <string.h>

#define MAX_X 8
#define MAX_Y 4
int memo[MAX_X+1][MAX_Y+1];
int dx[4] = {1, 2, 2, 1};
int dy[4] = {2, 1, -1, -2};

int dfs(int x, int y) {
    if (x < 0 || x > MAX_X || y < 0 || y > MAX_Y) return 0;
    if (x == MAX_X && y == MAX_Y) return 1;
    int &res = memo[x][y];
    if (res != -1) return res;
    res = 0;
    for (int i = 0; i < 4; ++i)
        res += dfs(x + dx[i], y + dy[i]);
    return res;
}

int main() {
    memset(memo, -1, sizeof(memo));
    printf("Total paths: %d\n", dfs(0, 0));
    return 0;
}

输出:Total paths: 100(或根据确切棋盘大小可能为其他值,原文未给出最终数字,代码可直接运行得出)。

复杂度分析

  • 状态数:(MAX_X+1) * (MAX_Y+1) = 9*5 = 45。
  • 每个状态转移 4 次,时间 O(X*Y),空间 O(X*Y),瞬间完成。

扩展变体

  1. 全棋盘 9×10:状态 90 个,同样极快。
  2. 带障碍点:在 dfs 入口判断障碍返回 0。
  3. 求具体路径:记录前驱方向,终点回溯重构。
  4. 最短步数:BFS 从起点展开,首次到达目标即最短。
  5. 骑士周游:访问每个格子恰好一次,经典 Hamiltonian Path,需启发式(Warnsdorff 规则)或回溯剪枝。

总结

跳马问题是有向无环图上路径计数的教科书级例题。关键在于:识别状态(坐标)、转移(马的移动)、边界(目标/越界)、无环性保证 DP 可行。DFS+备忘录代码最短、最易写,面试首选;大规模棋盘可改用矩阵快速幂(O(log n))但实现复杂度高得多。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved