LeetCode 983最低票价/记忆化搜索/动态规划

此题来自:https://leetcode-cn.com/problems/minimum-cost-for-tickets/
在这里插入图片描述
在这里插入图片描述

  • 这道题刚开始打算用所给的天数直接搜索,即每一个要乘车的天数,都穷举选票策略,然后保留一个参数当作这个票的期限(剩下多少天可以继续乘车)。
  • 换个思路,当前第i天买哪个票最划算取决于买个这个票后的i+1/i+7/i+30天之后继续花的钱最少(这是一个贪心策略,很明显如果买了7天的票了的话,这七天内是不需要再继续买了),这个贪心策略是没问题的:在这里一共只有三种策略,而我枚举了所有;如果那天不需要出行,就等于后面一天所以就从前往后搜索,所以这个时候每天都是一个状态,而不是只要出行的那天了,dp数组要设成和要出行的天数的最后一天一样长的数组,但是很明显可能会有重复搜索(比如选择1天票/7天票同样到达第7天,而第7天的最优解是同样的),所以需要建个备忘录,记忆化。
  • 当记忆化搜索写出来后,也就不难推出自底向上的dp转移方程了(但直接写出来还是相对较难理解)。

记忆化:

int dp(int i) {
        if (i > 365) {
            return 0;
        }
        if (memo[i] != -1) {
            return memo[i];
        }
        if (dayset.count(i)) {
            memo[i] = min(min(dp(i + 1) + costs[0], dp(i + 7) + costs[1]), dp(i + 30) + costs[2]);
        }
        else {
            memo[i] = dp(i + 1);
        }
        return memo[i];
    }

dp:

 int mincostTickets(vector<int>& days, vector<int>& costs) {
        int n = days.back();
        int dp[n + 1];
        unordered_set<int> dayset;
        for(int day:days) dayset.insert(day);
        memset(dp,0,sizeof(dp));
        for(int i = 1;i <= n; ++i){
            if(!dayset.count(i)) dp[i] = dp[i-1];
            else{
        //贪心的转移 最划算的肯定是从7/30天前买的票过来转移
                dp[i] = min(dp[i-1]+costs[0],min(dp[max(0,i-7)]+costs[1],dp[max(0,i-30)]+costs[2]));
            }
        }
        return dp[n];
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值