青训营创作活动主题3寻友之旅解法

169 阅读2分钟

当青训营遇上码上掘金

这里写一下我在 青训营主题创作活动中的主题3:寻友之旅 解题思路。

先贴上题目

小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)

请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)

这道题我用了递推法解答。

首先处理特殊情况n >= k时: 此时小青在小码右侧,由于公交车不能往回走,所以小青只能选择步行,于是 ans=nkans=n-k

n < k的情况下,

①对于i <= n,先预处理dp[0]到dp[n]:

dp[i]=nidp[i]=n-i

②对于i > n,递推公式为:

i为偶数dp[i]=min(dp[i1]+1,dp[i/2])dp[i]=min(dp[i-1]+1,dp[i/2])

i为奇数dp[i]=dp[i1]+1dp[i]=dp[i-1]+1

分析: 典型的递推题目,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;
 }