本题出自力扣题库第983题。题面大意如下:
有三种不同价格的火车票,一天有效的售价为 costs[0];七天有效的售价为 costs[1];三十天有效的售价为 costs[2。 如果我们在第2天买了一张7天有效的车票,那么我们可以连着旅行7天:第2、第3、第4、第5、第6、第7和第8天。 数组days给出需要旅行的日子,每一项是一个从1到365的整数。 返回完成在days中列出的每一天的旅行所需要的最低消费。
示例:
输入:days = [1,4,6,7,8,20], costs = [2,7,15]
输出:11
解释:
在第 1 天,你花了 costs[0] = $2 买了一张1天有效的车票,它可以用于第1天。
在第 3 天,你花了 costs[1] = $7 买了一张7天有效的车票,它可以用于第3, 4, ..., 9 天。
在第 20 天,你花了 costs[0] = $2 买了一张1天有效的车票,它可以用于第20天。
总共花费$11,完成days种的每一天的旅行。
题解:
本题的基本思路在于给定一个1到365之间的整数k,如果k不在days列表中,那么我们不用花钱就可递归到k+1,当k在days列表中,我们有三个选择:1)花费costs[0]然后递归到k+1;2)花费costs[1]然后递归到k+7;3)花费costs[2]然后递归到k+30,三者之间的最小值就是对k而言的答案。
Java代码如下:
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
class Solution {
int[] costs;
Set<Integer> dayset;
int lastDay;
int[] dp;
public int mincostTickets(int[] days, int[] costs) {
this.costs = costs;
this.lastDay = days[days.length - 1];
dp = new int[366];
dayset = new HashSet();
for (int day: days) {
dayset.add(day);
}
return helper(1);
}
public int helper(int i) {
if (i > lastDay) {
return 0;
}
if (dp[i] > 0) {
return dp[i];
}
int result;
if (dayset.contains(i)) {
int optionA = costs[0] + helper(i + 1);
int optionB = costs[1] + helper(i + 7);
int optionC = costs[2] + helper(i + 30);
result = Math.min(optionA, Math.min(optionB, optionC));
} else {
result = helper(i+1);
}
return dp[i] = result;
}
}