LCP 20. 快速公交

难度困难

小扣打算去秋日市集,由于游客较多,小扣的移动速度受到了人流影响:

  • 小扣从 x 号站点移动至 x + 1 号站点需要花费的时间为 inc
  • 小扣从 x 号站点移动至 x - 1 号站点需要花费的时间为 dec

现有 m 辆公交车,编号为 0 到 m-1。小扣也可以通过搭乘编号为 i的公交车,从 x 号站点移动至 jump[i]*x 号站点,耗时仅为 cost[i]。小扣可以搭乘任意编号的公交车且搭乘公交次数不限。

假定小扣起始站点记作 0,秋日市集站点记作 target,请返回小扣抵达秋日市集最少需要花费多少时间。由于数字较大,最终答案需要对 1000000007 (1e9 + 7) 取模。

注意:小扣可在移动过程中到达编号大于 target 的站点。

示例 1:

输入:target = 31, inc = 5, dec = 3, jump = [6], cost = [10]

输出:33

解释:
小扣步行至 1 号站点,花费时间为 5;
小扣从 1 号站台搭乘 0 号公交至 6 * 1 = 6 站台,花费时间为 10;
小扣从 6 号站台步行至 5 号站台,花费时间为 3;
小扣从 5 号站台搭乘 0 号公交至 6 * 5 = 30 站台,花费时间为 10;
小扣从 30 号站台步行至 31 号站台,花费时间为 5;
最终小扣花费总时间为 33。

示例 2:

输入:target = 612, inc = 4, dec = 5, jump = [3,6,8,11,5,10,4], cost = [4,7,6,3,7,6,4]

输出:26

解释:
小扣步行至 1 号站点,花费时间为 4;
小扣从 1 号站台搭乘 0 号公交至 3 * 1 = 3 站台,花费时间为 4;
小扣从 3 号站台搭乘 3 号公交至 11 * 3 = 33 站台,花费时间为 3;
小扣从 33 号站台步行至 34 站台,花费时间为 4;
小扣从 34 号站台搭乘 0 号公交至 3 * 34 = 102 站台,花费时间为 4;
小扣从 102 号站台搭乘 1 号公交至 6 * 102 = 612 站台,花费时间为 7;
最终小扣花费总时间为 26。

提示:

  • 1 <= target <= 10^9
  • 1 <= jump.length, cost.length <= 10
  • 2 <= jump[i] <= 10^6
  • 1 <= inc, dec, cost[i] <= 10^6

  从0开始往后进行路径查找会有很多条路径的可能,而从目标点往回进行查找就会减少很多可能,因此采用回溯法从目标点往回进行查找直至找到1(这是因为从0点出发必定需要一次INC到达1点),在回溯过程中到达当前点now可能存在的情况大体可以分为以下三种:

  1. 从0到now一直都是步行,即res = now * INC;
  2. 通过公交车i从p点到达p * jump[i] 后向后步行至now;
  3. 通过公交车i从p点到达(p + 1) * jump[i] 后向前步行至now;

      这里 p = floor(now / jump[i])

      需要注意的是由于会出现计算结果大于int类型范围的值,因此在int乘法计算时需要转换为long long类型,否则会执行错误!!!

class Solution { 
public:
	map<long long, long long > dp;
	int INC, DEC, Target,best = 0x3F3F3F3F;
	long long back_find(int now, vector<int>& jump, vector<int>& cost) {
		//cout << now << ' ' << dp[now] << endl;
		if (now == 0)
			return 0;
		if (dp.count(now))
			return dp[now];
		long long res = (long long)now * INC;
		for (int i = 0; i < jump.size(); ++i) {
			int p = floor(now / jump[i]);
			int q = now % jump[i];
			if(q > 0)		// 说明不是整除
				res = min(res, back_find(p + 1, jump, cost) + (long long)DEC * ((long long)jump[i] - q) + cost[i]);
			if (p > 0)
				res = min(res, back_find(p, jump, cost) + (long long)INC * q + cost[i]);
		}
		dp[now] = res;
		return res;
	}
	int busRapidTransit(int target, int inc, int dec, vector<int>& jump, vector<int>& cost) {
		INC = inc;
		DEC = dec;
		Target = target;
		dp[0] = 0;
		dp[1] = inc;
		if (target == 1)
			return dp[1];
		dp[Target] = back_find(target, jump, cost);
		return dp[Target] %1000000007 ;
	}
};

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值