当青训营遇上码上掘金:寻友之旅动态规划解法
主题 3:寻友之旅
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)
作者:青训营官方账号
链接:juejin.cn/post/717498…
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
动态规划解法:
- 小青在小码前面———— 步行回退 return N-K
- 小青就在小码位置—— return 0
- 小青在小码后面——动态规划
-
状态定义
int* dp = new int[100000] {}; //dp[i]:从N到i需要花费最短时间 -
初始状态
dp[N] = 0; // 从N到N需要花费0分钟 res = INT_MAX; // 最短时间初始化为INT_MAX -
结果:最短时间
/* res = min(从N到K的最短时间,从N到K+j再回退j的最短时间) = min (dp[K], dp[k+j]+j); */ -
状态转移
/* 0=<i<N——dp[i] = dp[i+1]+1; 步行回退 i>N————dp[i] = min(步行到i,总公交到i)+1 = min(dp[i-1], dp[i/2])+1; i-1>=0且i/2为偶数 = min(dp[i-1], dp[(i-1)/2]+1, dp[(i+1)/2]+1)+1; i-1>=0且i/2为奇数 */ for (int i = N - 1; i >= 0; i--) { dp[i] = dp[i + 1] + 1; } for (int i = N + 1; i <= 100000; i++) { int walk = dp[i - 1] + 1; int bus = dp[i / 2] + 1; if (i % 2 != 0) { bus = min(dp[(i + 1) / 2], dp[(i - 1) / 2]) + 2; } dp[i] = min(walk, bus); if (i >= K) { res = min(res, dp[i] + i - K); } }
-