In a country popular for train travel, you have planned some train travelling one year in advance. The days of the year that you will travel is given as an array days
. Each day is an integer from 1
to 365
.
Train tickets are sold in 3 different ways:
- a 1-day pass is sold for
costs[0]
dollars; - a 7-day pass is sold for
costs[1]
dollars; - a 30-day pass is sold for
costs[2]
dollars.
The passes allow that many days of consecutive travel. For example, if we get a 7-day pass on day 2, then we can travel for 7 days: day 2, 3, 4, 5, 6, 7, and 8.
Return the minimum number of dollars you need to travel every day in the given list of days
.
Example 1:
Input: days = [1,4,6,7,8,20], costs = [2,7,15]
Output: 11
Explanation:
For example, here is one way to buy passes that lets you travel your travel plan:
On day 1, you bought a 1-day pass for costs[0] = $2, which covered day 1.
On day 3, you bought a 7-day pass for costs[1] = $7, which covered days 3, 4, ..., 9.
On day 20, you bought a 1-day pass for costs[0] = $2, which covered day 20.
In total you spent $11 and covered all the days of your travel.
思路:典型的坐标型dp,跟coin change一样
dp[i]代表的是到目前为止的天数i, 我需要的最小cost是多少;
那么也就是dp[i] = Math.min(dp[i - 1] + cost[0], dp[i - 7] + cost[1] , dp[i - 30] + cost[2] );
如果不需要travel,dp[i] = dp[i - 1];
这题比较triky的地方是: i - 7 < 0, i - 30 < 0 的时候,需要dp[Math.max(0, i - 7)] dp[math.max(0, i - 30)]
原因就是:i - 7 , i - 30虽然越界了,但是我可以在第一天买7天和 30天的票,cover住4,5,6,这些小于7天的票;
class Solution {
// dp[i] = Math.min(dp[i], dp[i - 1] + cost[0], dp[i - 7] + cost[1], dp[i - 30] + cost[2]);
public int mincostTickets(int[] days, int[] costs) {
int n = days.length;
int lastDay = days[n - 1];
int[] dp = new int[lastDay + 1];
boolean[] travel = new boolean[lastDay + 1];
for(int i = 0; i < n; i++) {
travel[days[i]] = true;
}
for(int i = 1; i < dp.length; i++) {
if(!travel[i]) {
dp[i] = dp[i - 1];
} else {
dp[i] = dp[i - 1] + costs[0];
// dp[4,5,6] 都可以由dp[0] cover住,也就是我第一个天买7天的票,我只用到第4,5,6 也可以;
dp[i] = Math.min(dp[i], dp[Math.max(0, i - 7)] + costs[1]);
dp[i] = Math.min(dp[i], dp[Math.max(0, i - 30)] + costs[2]);
}
}
return dp[lastDay];
}
}