跳房子——动态规划

存在n+1个房间,每个房间依次为房间1 2 3…i,每个房间都存在一个传送门,i房间的传送门可以把人传送到房间pi(1<=pi<=i),现在路人甲从房间1开始出发(当前房间1即第一次访问),每次移动他有两种移动策略:

A. 如果访问过当前房间 i 偶数次,那么下一次移动到房间i+1;
B. 如果访问过当前房间 i 奇数次,那么移动到房间pi;

现在路人甲想知道移动到房间n+1一共需要多少次移动;
输入描述:
第一行包括一个数字n(30%数据1<=n<=100,100%数据 1<=n<=1000),表示房间的数量,接下来一行存在n个数字 pi(1<=pi<=i), pi表示从房间i可以传送到房间pi。
输出描述:
输出一行数字,表示最终移动的次数,最终结果需要对1000000007 (10e9 + 7) 取模。

思路:这道题对于我来说算是一个非常抽象的题目,我也是想了两天突然想通了,我试着给大家讲清楚。。。
我们定义一个dp[n+2]的数组,代表跳到当前房子次数为奇数次的步数,因为房子从1开始,一共有n+1个房子,所以数组长度定为n+2;在定义一个p[n+1]数组,代表执行A策略的时候,可以跳到的房子位置。
1、现在第一次跳到i-1房子的次数为奇数次那么之前的i-2个房子都已经跳了偶数次,不然不可能到i-1房子这里,此时执行B策略,跳到p[i-1],这过程中步数+1;
2、此时跳到p[i-1],他肯定是奇数次了,其他的门都是偶数次,那么这和第一次跳到p[i-1]房子的情况完全相同,那么再从p[i-1]房子跳到i-1房子的步数为dp[i-1]-dp[p[i-1]];
3、此时是第二次跳到i-1房子已经是偶数次了,此时执行A策略,向前跳一个房子,此时步数+1;
那么我们就得到了状态方程:dp[i] = dp[i-1]+1+dp[i-1]-dp[p[i-1]]+1;
代码如下:

import java.util.Scanner;
public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        long mod = 1000000007;
        int[] p = new int[n+1];
        long[] dp = new long[n+2];
        //表示当前跳到当前房子的奇数次
        for(int i=1;i<=n;i++){
            p[i] = sc.nextInt();
        }
        for(int i=2;i<n+2;i++){
            dp[i] = dp[i-1]+1+dp[i-1]-dp[p[i-1]]+1;
            dp[i] = dp[i]%mod;
        }
        System.out.println(dp[n+1]<0?dp[n+1]+mod:dp[n+1]);
    }
}

虽然代码很短,但是我觉得真的很难理解,害。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

宋丹尼尔

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

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

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

打赏作者

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

抵扣说明:

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

余额充值