当青训营遇上码上掘金
这里写一下我在 青训营主题创作活动中的主题3:寻友之旅 解题思路。
先贴上题目
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)
这道题我用了递推法解答。
首先处理特殊情况n >= k时: 此时小青在小码右侧,由于公交车不能往回走,所以小青只能选择步行,于是
在n < k的情况下,
①对于i <= n,先预处理dp[0]到dp[n]:
②对于i > n,递推公式为:
i为偶数时
i为奇数时
分析: 典型的递推题目,dp[i]表示小青走到第i点处所需要的最少时间,当i点在n点左侧时,只能通过步行走到,于是dp[i]=n-i;当i点在n右侧时,到达i点有两种方法:从i-1点步行向右前进一格或者从i/2乘坐公交到达i点,而i为奇数是只有从i-1点步行到i点一种方法,于是就有了以上的递推公式。
最后贴上代码:
#include <iostream>
using namespace std;
const int N = 100000+1;
int dp[N+5];
int main() {
int n = 0, k = 0, ans1 = 0;
cin >> n >> k;
if (n >= k) ans1 = n - k;
else {
for (int i = 0; i <= n; ++i) { //预处理dp[0]到[n]
dp[i] = n - i;
}
for (int i = n + 1; i <= k; i++) {
if ((i % 2 != 0)) {
dp[i] = dp[i - 1] + 1;
}
else {
dp[i] = min(dp[i - 1] + 1, dp[i / 2] + 1);
}
}
ans1 = dp[k];
}
cout << ans1;
return 0;
}