[编程题]滑雪 Java版 动态规划

看到一道有趣的编程题:

NowCoder喜欢滑雪,因为滑雪的确很刺激。为了获得速度,必须从高处往低处滑。现在知道某片区域的海拔,如下所示
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
可以从某个点滑向上下左右四个方向中海拔比当前位置低的点。例如上图中一条可行的滑坡为24-17-16-1。当然25-24-23-…-3-2-1是最长的一条。
现在给出区域的海拔,你能帮忙计算最长的滑道有多长吗?


输入描述:

输入包含多组数据。

每组数据的第一行包含两个正整数m和n (1≤m, n≤100),紧接着是m*n的海拔矩阵,包含各个点的高度h (1≤h≤10000)。

输出描述:

对应每一组数据,输出该区域最长的滑道长度。


输入例子:

5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
2 2
1 1
1 1

输出例子:

25
1

这是一道动态规划的问题,现在这这一步得出的结果会用到之前的结果。这道题我们可以用一个二维矩阵存放每一个点的到其最低点的“滑雪长度”,这样遍历所有的点时就不必重复计算每个点的“滑雪长度”了。下面是代码:

import java.util.*;

public class Main{

    private static int[][] arr; //存放输入的矩阵
    private static int[][] value; //对应arr没点的“滑雪长度”
    private static int c; //arr的列数
    private static int r; //arr的行数

    public static void main(String[] args){

        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
            r = sc.nextInt();
            c = sc.nextInt();
            int max = 0;
            arr = new int[r][c];
            value = new int[r][c];
            for (int i = 0; i < r; i++) {
                for (int j = 0; j < c; j++) {
                    arr[i][j] = sc.nextInt();
                }
            }
            for (int i = 0; i < r; i++) {
                for (int j = 0; j < c; j++) {
                    int temp = ski(i, j, Integer.MAX_VALUE);
                    if (temp > max) {
                        max = temp;
                    }
                }
            }
            System.out.println(max);

        }
        sc.close();
    }

    /**
     * @param col:arr的列数
     * @param row:arr的行数
     * @param maxValue:上一个arr点的值
     * @return
     */
    private static int ski(int row, int col, int maxValue) {
        //出了矩阵的区域或者现在arr这个点的值大于上一个arr点的值,即跑到更高的点去了,无效,返回0
        if (col >= c || col < 0 || row >= r || row < 0 || maxValue <= arr[row][col] ) {
            return 0;
        }
        //若已经计算过了此arr点的“滑雪长度”,直接返回
        if (value[row][col] > 0) {
            return value[row][col];
        }
        //不然就计算此点的“滑雪长度” = 上下左右的点的“滑雪长度”的最大值 + 1
        value[row][col] = max(ski(row-1, col, arr[row][col]), ski(row+1, col, arr[row][col]), ski(row, col-1, arr[row][col]), ski(row, col+1, arr[row][col])) + 1;
        return value[row][col];
    }

    /**
     * @param ski1
     * @param ski2
     * @param ski3
     * @param ski4
     * @return 最大值
     */
    private static int max(int ski1, int ski2, int ski3, int ski4) {
        return Math.max(Math.max(ski1, ski2), Math.max(ski3, ski4));
    }

}

运行结果:
运行结果

也通过了牛客网的所有测试用例:
这里写图片描述
牛客网地址:传送门

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值