(C卷,200分)- 园区参观路径(Java & JS & Python & C)

题目描述

园区某部门举办了Family Day,邀请员工及其家属参加;

将公司园区视为一个矩形,起始园区设置在左上角,终点园区设置在右下角;

家属参观园区时,只能向右和向下园区前进,求从起始园区到终点园区会有多少条不同的参观路径。

输入描述

第一行为园区的长和宽;

后面每一行表示该园区是否可以参观,0表示可以参观,1表示不能参观

输出描述

输出为不同的路径数量

用例

输入 3 3
0 0 0
0 1 0
0 0 0
输出 2
说明

题目解析

本题可以使用深度优先搜索解题。

因为深度优先搜索DFS的每一条递归分支都对应一条路径,如果某个递归分支可以走到终点位置,那么说明该递归分支对应的路径可达终点。

本题递归进入下一个位置的条件是:

  • 下一个位置在上一个位置的下边或右边
  • 下一个位置不越界
  • 下一个位置可以参观(矩阵元素值为0)

并且,本题限定只能从当前位置,向下或者向右进入下一个位置,因此不用担心走回头路的问题,即不用建立visited表记录走过的位置。

注意:本题没有数量级信息,因此如果存在大数量级的话,基于递归实现的深搜可能会发生StackOverFlow异常,因此更推荐使用基于栈结构实现的深搜


本题如果地图矩阵数量级过大的话,深搜解题会超时。因此,更优解法是利用动态规划,我们可以定义一个dp二维数组,dp[i][j]的含义是:从坐标(0,0)到达坐标(i, j)的路径数

而本题说只能向下或者向右运动,因此到达一个坐标点,可能来自其上方,亦可能来自其左方

因此 dp[i][j] = dp[i-1][j] + dp[i][j-1]

即:

如果到达(i-1,j)的路径有dp[i-1][j]条,那么到达(i,j)的路径也有dp[i-1][j]条

同理到达(i, j-1)的路径有dp[i][j-1],那么到达(i,j)的路径也有dp[i][j-1]条

因此:dp[i][j] = dp[i-1][j] + dp[i][j-1]

需要注意的是,dp[0][0] 初始化时,需要注意(0,0)坐标位置是否可以参观,如果不可以参观,则道道(0,0)的路径为0条,否则为1条。

其他点套用公式时,注意索引越界问题,具体请看代码实现。

JS算法源码

动态规划
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
  // 长n -> 行数, 宽m -> 列数
  const [n, m] = (await readline()).split(" ").map(Number);

  // 地图矩阵
  const matrix = [];
  for (let i = 0; i < n; i++) {
    matrix.push((await readline()).split(" ").map(Number));
  }

  // 如果起点和终点不能参观,则没有路径
  if (matrix[0][0] == 1 || matrix[n - 1][m - 1] == 1) {
    console.log(0);
    return;
  }

  const dp = new Array(n).fill(0).map(() => new Array(m).fill(0));
  dp[0][0] = 1;

  for (let i = 0; i < n; i++) {
    for (let j = 0; j < m; j++) {
      if (matrix[i][j] == 1) continue;

      if (i > 0) {
        dp[i][j] += dp[i - 1][j];
      }

      if (j > 0) {
        dp[i][j] += dp[i][j - 1];
      }
    }
  }

  console.log(dp[n - 1][m - 1]);
})();
基于递归实现的深搜
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
  // 长n -> 行数, 宽m -> 列数
  const [n, m] = (await readline()).split(" ").map(Number);

  // 地图矩阵
  const matrix = [];
  for (let i = 0; i < n; i++) {
    matrix.push((await readline()).split(" ").map(Number));
  }

  // 向下、向右的偏移量
  const offsets = [
    [1, 0],
    [0, 1],
  ];

  // 记录题解
  let ans = 0;

  function dfs(x, y) {
    if (x == n - 1 && y == m - 1) {
      // 如果当前分支可以走到终点,则对应分支路径可行
      ans++;
      return;
    }

    // 从当前位置(x, y)向下或者向右走
    for (let [offsetX, offsetY] of offsets) {
      // 新位置(newX, newY)
      const newX = x + offsetX;
      const newY = y + offsetY;

      // 如果新位置没有越界且新位置可以参观,则进入
      if (
        newX >= 0 &&
        newX < n &&
        newY >= 0 &&
        newY < m &&
        matrix[newX][newY] == 0
      ) {
        dfs(newX, newY);
      }
    }
  }

  // 从(0,0)位置开始深搜,深搜对应的每条分支都对应一条路径
  if (matrix[0][0] == 0) {
    dfs(0, 0);
  }

  console.log(ans);
})();
 基于栈实现的深搜
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
  // 长n -> 行数, 宽m -> 列数
  const [n, m] = (await readline()).split(" ").map(Number);

  // 地图矩阵
  const matrix = [];
  for (let i = 0; i < n; i++) {
    matrix.push((await readline()).split(" ").map(Number));
  }

  // 向下、向右的偏移量
  const offsets = [
    [1, 0],
    [0, 1],
  ];

  // 记录题解
  let ans = 0;

  function dfs() {
    const stack = [];

    if (matrix[0][0] == 0) {
      stack.push(0);
    }

    while (stack.length > 0) {
      const pos = stack.pop();

      const y = pos % m;
      const x = (pos - y) / m;

      if (x == n - 1 && y == m - 1) {
        ans++;
        continue;
      }

      for (let [offsetX, offsetY] of offsets) {
        const newX = x + offsetX;
        const newY = y + offsetY;

        if (
          newX >= 0 &&
          newX < n &&
          newY >= 0 &&
          newY < m &&
          matrix[newX][newY] == 0
        ) {
          stack.push(newX * m + newY);
        }
      }
    }
  }

  // 从(0,0)位置开始深搜,深搜对应的每条分支都对应一条路径
  dfs();

  console.log(ans);
})();

Java算法源码

动态规划
import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    int n = sc.nextInt(); // 长 -> 行数
    int m = sc.nextInt(); // 宽 -> 列数

    int[][] matrix = new int[n][m]; // 地图矩阵
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        matrix[i][j] = sc.nextInt();
      }
    }

    // 如果起点和终点不能参观,则没有路径
    if (matrix[0][0] == 1 || matrix[n - 1][m - 1] == 1) {
      System.out.println(0);
      return;
    }

    long[][] dp = new long[n][m];
    dp[0][0] = 1;

    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        if (matrix[i][j] == 1) continue;

        if (i > 0) {
          dp[i][j] += dp[i - 1][j];
        }

        if (j > 0) {
          dp[i][j] += dp[i][j - 1];
        }
      }
    }

    System.out.println(dp[n - 1][m - 1]);
  }
}
基于递归实现的深搜
import java.util.Scanner;

public class Main {
  static int n;
  static int m;
  static int[][] matrix;
  static int[][] offsets = {{1, 0}, {0, 1}};

  static int ans = 0;

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    n = sc.nextInt(); // 长 -> 行数
    m = sc.nextInt(); // 宽 -> 列数

    matrix = new int[n][m]; // 地图矩阵
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        matrix[i][j] = sc.nextInt();
      }
    }

    // 从(0,0)位置开始深搜,深搜对应的每条分支都对应一条路径
    if (matrix[0][0] == 0) {
      dfs(0, 0);
    }

    System.out.println(ans);
  }

  public static void dfs(int x, int y) {
    if (x == n - 1 && y == m - 1) {
      // 如果当前分支可以走到终点,则对应分支路径可行
      ans++;
      return;
    }

    // 从当前位置(x, y)向下或者向右走
    for (int[] offset : offsets) {
      // 新位置(newX, newY)
      int newX = x + offset[0];
      int newY = y + offset[1];

      // 如果新位置越界了,或者新位置不能参观,则无法进入
      if (newX < 0 || newX >= n || newY < 0 || newY >= m || matrix[newX][newY] == 1) continue;

      // 否则进入新位置,继续深搜
      dfs(newX, newY);
    }
  }
}
基于栈实现的深搜
import java.util.LinkedList;
import java.util.Scanner;

public class Main {
  static int n;
  static int m;
  static int[][] matrix;
  static int[][] offsets = {{1, 0}, {0, 1}};

  static int ans = 0;

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    n = sc.nextInt(); // 长 -> 行数
    m = sc.nextInt(); // 宽 -> 列数

    matrix = new int[n][m]; // 地图矩阵
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        matrix[i][j] = sc.nextInt();
      }
    }

    dfs();

    System.out.println(ans);
  }

  public static void dfs() {
    LinkedList<Integer> stack = new LinkedList<>();

    if (matrix[0][0] == 0) {
      stack.addLast(0);
    }

    while (stack.size() > 0) {
      int pos = stack.removeLast();

      int x = pos / m;
      int y = pos % m;

      if (x == n - 1 && y == m - 1) {
        ans++;
        continue;
      }

      for (int[] offset : offsets) {
        int newX = x + offset[0];
        int newY = y + offset[1];

        if (newX >= 0 && newX < n && newY >= 0 && newY < m && matrix[newX][newY] == 0) {
          stack.addLast(newX * m + newY);
        }
      }
    }
  }
}

Python算法源码

动态规划
# 输入获取
n, m = map(int, input().split())  # // 长n -> 行数, 宽m -> 列数
matrix = [list(map(int, input().split())) for _ in range(n)]  # 地图矩阵


# 算法入口
def getResult():
    # 如果起点和终点不能参观,则没有路径
    if matrix[0][0] == 1 or matrix[n - 1][m - 1] == 1:
        return 0

    dp = [[0 for _ in range(m)] for _ in range(n)]
    dp[0][0] = 1

    for i in range(n):
        for j in range(m):
            if matrix[i][j] == 1:
                continue

            if i > 0:
                dp[i][j] += dp[i - 1][j]

            if j > 0:
                dp[i][j] += dp[i][j - 1]

    return dp[n - 1][m - 1]


# 算法调用
print(getResult())
基于递归实现的深搜
# 输入获取
n, m = map(int, input().split())  # // 长n -> 行数, 宽m -> 列数
matrix = [list(map(int, input().split())) for _ in range(n)]  # 地图矩阵

# 向下、向右的偏移量
offsets = ((1, 0), (0, 1))

# 记录题解
ans = 0


# 深搜
def dfs(x, y):
    global ans

    if x == n - 1 and y == m - 1:
        # 如果当前分支可以走到终点,则对应分支路径可行
        ans += 1
        return

    # 从当前位置(x, y)向下或者向右走
    for offsetX, offsetY in offsets:
        # 新位置(newX, newY)
        newX = x + offsetX
        newY = y + offsetY

        # 如果新位置没有越界且新位置可以参观,则进入
        if n > newX >= 0 and m > newY >= 0 and matrix[newX][newY] == 0:
            dfs(newX, newY)


# 算法调用
if matrix[0][0] == 0:
    dfs(0, 0)  # 从(0,0)位置开始深搜,深搜对应的每条分支都对应一条路径
print(ans)
基于栈实现的深搜
# 输入获取
n, m = map(int, input().split())  # // 长n -> 行数, 宽m -> 列数
matrix = [list(map(int, input().split())) for _ in range(n)]  # 地图矩阵

# 向下、向右的偏移量
offsets = ((1, 0), (0, 1))

# 记录题解
ans = 0


# 深搜
def dfs():
    global ans

    stack = []

    if matrix[0][0] == 0:
        stack.append(0)

    while len(stack) > 0:
        pos = stack.pop()

        x = pos // m
        y = pos % m

        if x == n - 1 and y == m - 1:
            ans += 1
            continue

        for offsetX, offsetY in offsets:
            newX = x + offsetX
            newY = y + offsetY

            if n > newX >= 0 and m > newY >= 0 and matrix[newX][newY] == 0:
                stack.append(newX * m + newY)


# 算法调用
dfs()
print(ans)

C算法源码

动态规划
#include <stdio.h>

int main() {
    // 长n -> 行数, 宽m -> 列数
    int n, m;
    scanf("%d %d", &n, &m);

    // 地图矩阵,这里把二维压缩为了一维
    int matrix[n][m];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            // 由于matrix是一维数组,所以这里(i, j)二维坐标也要转成一维坐标
            scanf("%d", &matrix[i][j]);
        }
    }

    if (matrix[0][0] == 1 || matrix[n - 1][m - 1] == 1) {
        puts("0");
        return 0;
    }

    long dp[n][m];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            dp[i][j] = 0;
        }
    }

    dp[0][0] = 1;

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (matrix[i][j] == 1) continue;

            if (i > 0) {
                dp[i][j] += dp[i - 1][j];
            }

            if (j > 0) {
                dp[i][j] += dp[i][j - 1];
            }
        }
    }

    printf("%ldn", dp[n - 1][m - 1]);

    return 0;
}
基于递归实现的深搜
#include <stdio.h>
#include <stdlib.h>

// 长n -> 行数, 宽m -> 列数
int n, m;

// 地图矩阵,这里把二维压缩为了一维
int *matrix;

// 向下、向右的偏移量
int offsets[2][2] = {{1, 0},
                     {0, 1}};

// 记录题解
int ans = 0;

void dfs(int x, int y) {
    if (x == n - 1 && y == m - 1) {
        // 如果当前分支可以走到终点,则对应分支路径可行
        ans += 1;
        return;
    }

    // 从当前位置(x, y)向下或者向右走
    for (int i = 0; i < 2; i++) {
        // 新位置(newX, newY)
        int newX = x + offsets[i][0];
        int newY = y + offsets[i][1];

        // 如果新位置没有越界且新位置可以参观,则进入
        if (newX >= 0 && newX < n && newY >= 0 && newY < m && matrix[newX * m + newY] == 0) {
            dfs(newX, newY);
        }
    }
}

int main() {
    scanf("%d %d", &n, &m);

    matrix = (int *) calloc(n * m, sizeof(int));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            // 由于matrix是一维数组,所以这里(i, j)二维坐标也要转成一维坐标
            scanf("%d", &matrix[i * m + j]);
        }
    }

    // 从(0,0)位置开始深搜,深搜对应的每条分支都对应一条路径
    if(matrix[0] == 0) {
        dfs(0, 0);
    }

    printf("%dn", ans);

    return 0;
}
基于栈实现的深搜
#include <stdio.h>
#include <stdlib.h>

// 自定义栈结构(数组)的容量,不够再加
#define MAX_SIZE 10000

// 长n -> 行数, 宽m -> 列数
int n, m;

// 地图矩阵,这里把二维压缩为了一维
int *matrix;

// 向下、向右的偏移量
int offsets[2][2] = {{1, 0},
                     {0, 1}};

// 记录题解
int ans = 0;

void dfs() {
    int stack[MAX_SIZE];
    int stack_size = 0;

    if(matrix[0] == 0) {
        stack[stack_size++] = 0;
    }

    while(stack_size > 0) {
        int pos = stack[--stack_size];

        int x = pos / m;
        int y = pos % m;

        if(x == n - 1 && y == m - 1) {
            ans++;
            continue;
        }

        for(int i=0; i<2; i++) {
            int newX = x + offsets[i][0];
            int newY = y + offsets[i][1];

            if(newX >= 0 && newX < n && newY >= 0 && newY < m && matrix[newX * m + newY] == 0) {
                stack[stack_size++] = newX * m + newY;
            }
        }
    }
}

int main() {
    scanf("%d %d", &n, &m);

    matrix = (int *) calloc(n * m, sizeof(int));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            // 由于matrix是一维数组,所以这里(i, j)二维坐标也要转成一维坐标
            scanf("%d", &matrix[i * m + j]);
        }
    }

    dfs();

    printf("%dn", ans);

    return 0;
}

免责声明:

1、IT资源小站为非营利性网站,全站所有资料仅供网友个人学习使用,禁止商用
2、本站所有文档、视频、书籍等资料均由网友分享,本站只负责收集不承担任何技术及版权问题
3、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除下载链接并致以最深的歉意
4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
5、一经注册为本站会员,一律视为同意网站规定,本站管理员及版主有权禁止违规用户
6、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和IT资源小站的同意
7、IT资源小站管理员和版主有权不事先通知发贴者而删除本文

0

评论0

站点公告

没有账号?注册  忘记密码?