跳石板(动态规划)

一、跳石板

1、题目描述
题目链接
在这里插入图片描述
2、题目分析 + 解决

(1)

  1. 状态方程:F[ i ]表示跳到 map[ i ]位置所需要的最小步数(-1表示跳不到)
  2. 状态转移方程:向前遍历,直接从 j = i - 2开始,map[ j ] 为 -1 的位置跳过,如果 map[ i ] 与 map[ j ] 的差值是 array[ j ] 的约束,F[ i ] = min(F[ j ] + 1,F[ i ])
  3. 初始状态:F[ 0 ] = 0,F[ 1 ] = -1
  4. 返回结果:返回 F[ len -1 ]
  5. 但是这种方法时间复杂度是 O( n^2 ),测试不通过
    public static void main2(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int begin = scanner.nextInt();
        int end = scanner.nextInt();
        int len = end - begin + 1;
        int[] map = new int[len];
        
        for (int i = 0; i < len; i++) {
            map[i] = begin++;
        }
        int[] result = new int[len];

        result[0] = 0;
        result[1] = -1;
        for (int i = 2; i < len; i++) {
            for (int j = i - 2; j >= 0; j--) {
                int diffe = map[i] - map[j];
                if(diffe > map[j]/2){
                    break;
                }
                if(map[j] == -1 || map[j] % diffe != 0){
                    continue;
                }
                if(result[i] == 0){
                    result[i] = result[j] + 1;
                } else {
                    result[i] = Math.min(result[j] + 1, result[i]);
                }
            }
            if(result[i] == 0){
                result[i] = -1;
            }
        }

        System.out.println(result[len - 1]);
    }

(2)换种方法

  1. 状态方程:F[ i ]表示跳到 map[ i ]位置所需要的最小步数(-1表示跳不到)
  2. 状态转移方程:站在 map[ i ] 的位置上(若F[ i ] = -1,跳过这个位置),找到 map[ i ] 的因子(j…),可以得到从 map[ i ] 跳到某些位置(F[ i + j ]…)的步数(F[ i ] + 1);当F[ i + j ] = -1时,F[ i + j ] = F[ i ] + 1;否则取 min( F[ i ] +1,F[ i + j ] )
  3. 初始状态:除 F[ 0 ] = 0,其他位置均为 -1
  4. 返回结果:返回 F[ len - 1 ]
  5. 时间复杂度:O( n* 根号n )
public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int begin = scanner.nextInt();
        int end = scanner.nextInt();
        int len = end - begin + 1;

        int[] map = new int[len];
        for (int i = 0; i < len; i++) {
            map[i] = begin++;
        }

        int[] result = new int[len];
        for (int i = 1; i < len; i++) {
            result[i] = -1;
        }

        for (int i = 0; i < len; i++) {
            // 1. 说明不能跳到这个位置
            if(result[i] == -1){
                continue;
            }
            // 2. 求 map[i] 的因子
            Set<Integer> set = div(map[i]);
            // 3. 更新当前位置所能跳到的位置 的最小步数
            for (int val : set) {
                if(i + val < len){
                    if(result[i + val] == -1){
                        result[i + val] = result[i] + 1;
                    } else {
                        result[i + val] = Math.min(result[i + val], result[i] + 1);
                    }
                }
            }
        }
        System.out.println(result[len - 1]);
    }

    public static Set<Integer> div(int val){
        Set<Integer> set = new HashSet<>();
        for (int i = 2; i <= Math.sqrt(val); i++) {
            if(val % i == 0 ){
                set.add(i);
                set.add(val / i);
            }
        }
        return set;
    }

渤海名市,尚武之乡

河北沧州
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

威少总冠军

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

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

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

打赏作者

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

抵扣说明:

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

余额充值