防止动态规划的无限循环

防止动态规划的无限循环

算法概论第十二周


818. Race Car —— 题目链接

题目描述

Your car starts at position 0 and speed +1 on an infinite number line.  (Your car can go into negative positions.)

Your car drives automatically according to a sequence of instructions A (accelerate) and R (reverse).

When you get an instruction "A", your car does the following: position += speed, speed *= 2.

When you get an instruction "R", your car does the following: if your speed is positive then speed = -1 , otherwise speed = 1.  (Your position stays the same.)

For example, after commands "AAR", your car goes to positions 0->1->3->3, and your speed goes to 1->2->4->-1.

Now for some target position, say the length of the shortest sequence of instructions to get there.

Example 1:
Input: 
target = 3
Output: 2
Explanation: 
The shortest instruction sequence is "AA".
Your position goes from 0->1->3.
Example 2:
Input: 
target = 6
Output: 5
Explanation: 
The shortest instruction sequence is "AAARA".
Your position goes from 0->1->3->7->7->6.
 

Note:

1 <= target <= 10000.

思路分析

  • 寻找最优子问题
    • 没有必要考虑负值坐标
    • 在冲过终点后,继续往前加速是没必要的
  • 所以,找到的子问题是:
    • n = floor(log2(target)) + 1
    • 如果刚刚好加速n次刚好到达,是最好的
    • 如果冲n步过终点后回头,可以看成子问题racecar((1 << n) - 1 - target)
    • 如果冲n-1步,反向再冲m(0<m<n)步,再反向,以1的速度,继续进行子问题racecar(target - (1 << (n - 1)) + (1 << m))

实现代码

int[] dp = new int[10001];
public int racecar(int t) {
   if (dp[t] > 0) return dp[t]; // 如果dp[t]已计算过则直接返回
   int n = (int)(Math.log(t) / Math.log(2)) + 1;
   if (1 << n == t + 1) dp[t] = n; // 1<<n-1=t 表示一路狂奔A就能到达target
   else {
       dp[t] = racecar((1 << n) - 1 - t) + n + 1; // 狂奔A到第一次冲过target,然后R,然后剩下的距离作为子问题递归求解
       for (int m = 0; m < n - 1; ++m)
           dp[t] = Math.min(dp[t], racecar(t - (1 << (n - 1)) + (1 << m)) + n + m + 1);  // 标记1
   }
   return dp[t];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值