題目來源:力扣
題目介紹:
在一個火車旅行很受歡迎的國度,你提前一年計劃了一些火車旅行。在接下來的一年裏,你要旅行的日子將以一個名爲 days 的數組給出。每一項是一個從 1 到 365 的整數。
火車票有三種不同的銷售方式:
一張爲期一天的通行證售價爲 costs[0] 美元;
一張爲期七天的通行證售價爲 costs[1] 美元;
一張爲期三十天的通行證售價爲 costs[2] 美元。
通行證允許數天無限制的旅行。 例如,如果我們在第 2 天獲得一張爲期 7 天的通行證,那麼我們可以連着旅行 7 天:第 2 天、第 3 天、第 4 天、第 5 天、第 6 天、第 7 天和第 8 天。
返回你想要完成在給定的列表 days 中列出的每一天的旅行所需要的最低消費。
審題:
該題屬於一道較簡單的最優化問題, 我們可以使動態規劃算法解決.
當前的狀態量爲剩餘的尚未旅行的最早日期在數組中的下標.如果我們知道第days[i+1], days[i+2], …days[days.length-1]時的最優方案, 則我們可以計算得到days[i]的最優方案.在每一步, 我們有三種可能選擇.
如果我們選擇購買一張爲期一天的通行證, 則:
如果我們選擇購買一張爲期七天的通行證,則:
如果我們選擇購買一張爲期30天的通行證,則:
我們選擇最優的方式購買通行證即可.
class Solution {
public int mincostTickets(int[] days, int[] costs) {
//當前剩餘的待旅行日期第一個下標
//每一次, 我們可以選擇三種類型的通行證
int[] S = new int[days.length+1];
int minTickets = costs[0];
for(int cost: costs)
minTickets = Math.min(minTickets, cost);
S[days.length-1] = minTickets;
for(int i = days.length-2; i >= 0; i--){
int min = Integer.MAX_VALUE;
//如果購買一天的通行證,
min = Math.min(min, costs[0]+S[i+1]);
//如果購買七天的通行證, 則需要判斷從當前天起七天能夠包括哪些
int j = i;
while(j < days.length && days[i] + 7 > days[j])
j++;
min = Math.min(min, costs[1] + S[j]);
//如果購買30天的通行證,
j = i;
while(j < days.length && days[i] + 30 > days[j])
j++;
min = Math.min(min, costs[2] + S[j]);
S[i] = min;
}
return S[0];
}
}