题目的链接在这里: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]];
}
}