java leetcode之[动态规划 中等]983. 最低票价

题目的链接在这里:https://leetcode-cn.com/problems/minimum-cost-for-tickets/


题目大意

在一个火车旅行很受欢迎的国度,你提前一年计划了一些火车旅行。在接下来的一年里,你要旅行的日子将以一个名为 days 的数组给出。每一项是一个从 1 到 365 的整数。

火车票有三种不同的销售方式:

一张为期一天的通行证售价为 costs[0] 美元;
一张为期七天的通行证售价为 costs[1] 美元;
一张为期三十天的通行证售价为 costs[2] 美元。
通行证允许数天无限制的旅行。 例如,如果我们在第 2 天获得一张为期 7 天的通行证,那么我们可以连着旅行 7 天:第 2 天、第 3 天、第 4 天、第 5 天、第 6 天、第 7 天和第 8 天。

返回你想要完成在给定的列表 days 中列出的每一天的旅行所需要的最低消费。


一、示意图

在这里插入图片描述

二、解题思路

正常的动态规划

正常的动态规划

代码如下:

class Solution {
  public int mincostTickets(int[] days, int[] costs) {
        /**
         * 火车旅行 days是要旅行的日子  cost是分别 一天的价格 七天的价格 和三十天的价格
         *
         */
        //先进行边界判断
        if(days==null||days.length==0||costs==null||costs.length==0){
            return 0;
        }
        //dp[i]表示到 当天花的最低票价 先进行初始化 前一个是找到最晚一天是几天 后面+3是为了扩大范围 防止出现RuntimeException
        //应该是这样 dp[i]表示的是 我到达这一天 是花费了几天的门票
        int[] dp=new int[days[days.length-1]+3];
        //然后是起始状态
        dp[0]=0;
        //以及那些要买票的日子先进行初始化
        for(int day:days){
            dp[day]=Integer.MAX_VALUE;
        }

        //然后开始遍历 day是要旅行的日子 旅行当天买票
        for(int i=1;i<dp.length;i++){
            //说明没有被初始化过 那也就不需要买票 那他的价格就和他前面一天的价格一样
            if(dp[i]==0){
                dp[i]=dp[i-1];
            }
            else{
                /**我第i天要买票也就是i这样要旅行 有三种票可以买  所以是选每一种票的情况下 能实现的最低价格
                * 首先我在这一天买一天的票 就相当于就玩这一天 那我的前就是 dp[i-1]+cost[i]
                 * 那比如我这一天 我买的是七天的票 为什么就变成了七天前加上现在的花费了呢
                 * 如果把 dp[i]当作我到达这一天要旅行的时候 花费的是几天的门票比较合理 之前是因为我不旅行 所以那些天顺势叠加即可
                 * 如果我选的是 我买的是一天的门票达到的这一天旅行 那我就是 dp[i-1]+cost[0]
                 * 如果我选的是 我买的是 七天的门票达到的这旅行 i>=7的话 那就是我七天前 包括第七天 那天的花费买了这个票  如果不到七天的话 那就变成了我在第一天就买了票 然后到了这里
                 * 所以也就花了我买七天票的前
                 *
                 * 同理第30天也是这样
                 **/
                //那就是说明他需要买票的 那就进行判断他是买多少的票便宜呢 分别是 买一天 买七天 和买三十天
                //首先是买一天的话
                int n1=dp[i-1]+costs[0];
                //买七天的话 一种是你没超过七天 那就只能直接买七天的价格 一种是你超过了七天 那现在的花费就是 i-7天前的花费加上买七天的花费
                int n2=i>=7?dp[i-7]+costs[1]:costs[1];
                //同理 买三十天的话
                int n3=i>=30?dp[i-30]+costs[2]:costs[2];

                //然后找其中的最小值
                dp[i]=Math.min(n1,Math.min(n2,n3));
            }
        }
        //最后返回的就是达到最后一天的花费了
        return dp[days[days.length-1]];
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值