leetcode: 最低票價

題目來源:力扣

題目介紹:

在一個火車旅行很受歡迎的國度,你提前一年計劃了一些火車旅行。在接下來的一年裏,你要旅行的日子將以一個名爲 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]的最優方案.在每一步, 我們有三種可能選擇.
如果我們選擇購買一張爲期一天的通行證, 則:
S[i]=cost[0]+S[i+1]S[i] = cost[0] + S[i+1]
如果我們選擇購買一張爲期七天的通行證,則:
S[i]=cost[1]+S[j],days[j1]<days[i]+7<=days[j]S[i] = cost[1] + S[j], days[j-1] < days[i]+7 <= days[j]
如果我們選擇購買一張爲期30天的通行證,則:
S[i]=cost[2]+S[j],days[j1]<days[i]+30<=days[j]S[i] = cost[2] + S[j], days[j-1] < days[i]+30 <= days[j]
我們選擇最優的方式購買通行證即可.

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];
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章