Family Day/园区参观路径(C语言)

题目来自于博主算法大师的专栏:最新华为OD机试C卷+AB卷+OJ(C++JavaJSPy) https://blog.csdn.net/banxia_frontend/category_12225173.html

题目描述

园区某部门举办了Family Day,邀请员工及其家属参加;
将公司园区视为一个矩形,起始园区设置在左上角,终点园区设置在右下角;
家属参观园区时,只能向右和向下园区前进,求从起始园区到终点园区会有多少条不同的参观路径。

输入描述

第一行为园区的长和宽;
后面每一行表示该园区是否可以参观,0表示可以参观,1表示不能参观

输出描述

输出为不同的路径数量

用例

输入

3 3
0 0 0
0 1 0
0 0 0

输出

2

思路

动态规划(Dynamic Programming, DP)是一种在数学、管理科学、计算机科学、经济学等多领域中用于求解最优化问题的算法思想。它主要针对具有重叠子问题和最优子结构的问题,通过将复杂问题分解为相对简单的子问题,并存储并重用这些子问题的解以减少重复计算,从而得到原问题的最优解或所有可能解的数量。

在本题中,我们要求的是从园区左上角到右下角有多少种不同的参观路径。这个问题符合动态规划的应用场景:

  1. 重叠子问题:在计算到达某个园区的不同路径数量时,会涉及到到达其上方和左侧园区的路径数量。例如,在计算 (i, j) 园区的路径数时,需要知道 (i-1, j)(i, j-1) 的路径数,这意味着当我们计算其他位置时,可能会再次用到这些信息。

  2. 最优子结构:问题的最优解可以通过组合其子问题的最优解来构造。具体来说,(i, j) 位置的路径数量等于其上方 (i-1, j) 和左侧 (i, j-1) 两个位置路径数量之和,前提是当前位置是可以参观的。

因此,我们可以采用一个二维数组 dp 来保存每个园区的路径数量,初始化时,左上角园区(起点)的路径数量为1,然后按照从上到下、从左到右的顺序遍历整个园区,根据每个园区是否可参观以及与相邻园区的关系来递推计算每个园区的路径数量。最终,右下角园区(终点)的路径数量即为所求答案。

代码

思路一:

#include <stdio.h>
#include <stdlib.h>
int main() {
    int m, n;
    scanf("%d %d", &m, &n);
    int matrix[m][n];
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            scanf("%d", &matrix[i][j]);
        }
    }

    int dp[100][100];
    for (int i = 0; i < n && matrix[0][i] != 1; i++) {
        dp[0][i] = 1;
    }
    for (int i = 0; i < m && matrix[i][0] != 1; i++) {
        dp[i][0] = 1;
    }
    for (int i = 1; i < m; i++) {
        for (int j = 1; j < n; j++) {
            if (matrix[i][j] == 1) {
                continue;
            }
            dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
        }
    }
    printf("%d", dp[m - 1][n - 1]);
    return 0;
}

思路二:

#include <stdio.h>
#include <stdlib.h>

int main() {
    // 读取园区的行数(高)和列数(宽)
    int m, n;
    scanf("%d %d", &m, &n);

    // 初始化一个m×n的二维数组map,用于存储每个园区是否可以参观
    int map[m][n];
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            // 读取输入数据,0表示园区可参观,1表示不可参观
            scanf("%d", &map[i][j]);
        }
    }

    // 初始化一个与map同样大小的二维数组dp,用于动态规划计算不同路径数量
    int dp[m][n];

    // 动态规划遍历整个园区
    for (int i = 0; i < m; i++) {     // 遍历行
        for (int j = 0; j < n; j++) { // 遍历列

            // 当前园区可参观时
            if (map[i][j] == 0) {
                // 如果在起点(0, 0),则只有一种路径(自身)
                if (i == 0 && j == 0) {
                    dp[i][j] = 1;
                }
                // 如果在第一列(即只有向右的移动),则当前园区的路径数等于上一行同列园区的路径数
                else if (i == 0) {
                    dp[i][j] = dp[i][j - 1];
                }
                // 如果在第一行(即只有向下的移动),则当前园区的路径数等于上一列同行园区的路径数
                else if (j == 0) {
                    dp[i][j] = dp[i - 1][j];
                }
                // 对于其他园区,其路径数等于上一行同列园区路径数加上上一列同行园区路径数
                else {
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
                }
            }
            // 当前园区不可参观时,路径数为0
            else {
                dp[i][j] = 0;
            }
        }
    }

    // 输出从起始园区到终点园区的不同参观路径数量
    printf("%d\n", dp[m - 1][n - 1]); // 结束位置是(m-1, n-1),即右下角园区

    return 0; // 程序执行成功返回0
}

这段代码通过动态规划的方法解决了给定问题。它首先读取矩形园区的大小以及每个园区的可访问性,然后使用二维数组dp来记录从左上角到达每个园区的不同路径数量,并根据当前位置相对于上一行或上一列园区的关系来递推计算路径数。最后输出从左上角到右下角的路径总数。

注意细节:

for (int i = 0; i < n && matrix[0][i] != 1; i++) 

其中的

matrix[0][i] != 1;

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~柠月如风~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值