蓝桥杯——滑行(树形DP)

蓝桥杯——滑行(树形DP)

  • 题目链接 https://www.lanqiao.cn/problems/2414/learning

  • 题目理解:就是一个int dfs()问题,但是不加任何优化肯定会超时!mlgb,蓝桥杯好像压根不考那种简单数据结构题。四条路径用dfs遍历,记录层数,每次递归进行比较是否为最大层数。

  • 优化:采用树形DP的思想,就是 从叶子结点开始往上面加层数,每次遇到层数已经被记录的点,直接返回,就不需要再看它的孩子结点(周围结点)。本题中就是遇到一个点就遍历它的周围结点,就递归,在下一次函数中判断点是否合法。递归函数最终返回的是该结点的最大滑行距离。从什么时候开始赋值呢?从叶结点,这里也就是终点,此时遍历周围四个点都不合法,返回0,那么每个递归函数里面的int maxL = 0 ,就仍然是0,本结点的遍历仍然是0,那么最终返回dp[x][y] = maxL + 11。返回到上一层的循环遍历中,此时上一层的maxL就为1了,如果恰巧上一层那个点周围全都是终点,那maxL就为1,最终d[x][y] = maxL + 12。依次递推,就好像是已知该点周围结点的最大滑行距离,取最大的,然后+1就得到该点的最大滑行距离距离。

  • 注意:树形DP也算是一个非常规范的算法,很正规,目前没看到变种,一定要记住,并且一定要理解它的应用场合。 就比如这道题,就好像是求每个结点到叶结点的最大距离(叶结点到自己本身距离为1)。而且这道题不需要标记哪些点你已经访问过了,而是需要将所给图中的,全部点进行访问,如果该点的dp[x][y]!=0说明先前访问过了,那么这就直接返回,看这点是否是比目前得到的全局最大距离还大,如果是则替换,反之则不用改变。但是如果该点dp[x][y]==0,说明没访问过,那就需要老老实实进行树形DP求解,中间可能遇到已知dp[][]的点,直接返回最为此次循环与最大值maxL比较的值。只要从一个点出发,树形DP遍历过的点都会求得dp[x][y]这个值。

  • 代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    /*
        从前往后的思想是不行的,每次求得一个点的最大滑行距离再标记没什么用。
        因为你就算遇到了这个点,你也要确定这个点是否应该是正确的,可能经过其他点的滑行距离最大呢?
    
        这个思想一定要记住,每次到终点返回1,m=0 mx=1,而后自己本身又要经过为1,所以最大为2。
        主要操作为一个max和mx+1
        这种树形dfs一定要会。
    */
    
    int n, m, h[103][103], sum = 0, dp[103][103];
    int dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0};
    int maxLength;
    
    // 传入的 x, y 为出发点或者经过点。
    // 这样的写法可以得到每个点的最长距离。
    int dfs(int x, int y)
    {
        if (x < 1 || x > n || y < 1 || y > m)
            return 0;
    
        if(dp[x][y])
            return dp[x][y];
    
        int maxL = 0;
        // 表示可走的方向为4个
        for (int k = 0; k <= 3; k++)
        {
            // 换方向走
            int tx = x + dx[k], ty = y + dy[k];
            // 表示可以走
            if (h[tx][ty] < h[x][y])
            {
                maxL = max(maxL, dfs(tx, ty));
            }
        }
        // maxL 表示先前点的最大值。树形DP!这就是啊!
        dp[x][y] = maxL + 1;
        return dp[x][y];
    }
    int main()
    {
    
        int maxL = 0;
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= m; j++)
            {
                cin >> h[i][j];
            }
        }
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= m; j++)
            {
                maxL = max(maxL, dfs(i, j));
            }
        }
        // cout << "dp动态规划矩阵为:" << endl;
        // for (int i = 1; i <= n; i++)
        // {
        //     for (int j = 1; j <= m; j++)
        //     {
        //         cout << dp[i][j] << " ";
        //     }
        //     cout << endl;
        // }
        cout << maxL << endl;
        return 0;
    }
    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
滑行是指物体在无外力作用下沿斜面自由下滑的过程。要用Python来模拟滑行,首先需要知道滑行的物理规律和相关参数。 滑行的物理规律可用牛顿第二定律表达:物体在斜面上所受的重力分解成平行于斜面的重力分量和垂直于斜面的分力,在无空气阻力的情况下,该分力恰好等于斜面上的摩擦力,由此可以得到滑行加速度的表达式。 在Python中,可以通过定义滑行对象的质量、斜面的倾角、滑行对象与斜面之间的摩擦系数等参数来进行模拟。 首先,可以使用input函数获取用户输入的相关参数,例如质量m、斜面倾角theta和摩擦系数mu。 然后,根据滑行对象所受的重力和斜面的倾角,可以计算出平行于斜面的重力分量和垂直于斜面的分力。 由于无空气阻力,垂直于斜面的分力恰好等于斜面上的摩擦力,可以根据摩擦力的表达式计算出摩擦力的大小。 接下来,根据牛顿第二定律,可以计算滑行对象的加速度,即滑行加速度的大小。 最后,可以使用循环结构来模拟滑行的过程。根据滑行速度的变化规律,每次更新速度并计算滑行距离,直到速度降为0时停止。 在循环过程中,可以输出滑行的时间、滑行的距离等信息,以及调用相关的Python库函数和方法来实现数学计算、数值处理等操作。 通过以上步骤和代码实现,可以通过Python来模拟滑行的过程,得到滑行距离、滑行时间等数据,进一步了解滑行现象并进行分析。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值