[leetcode日記]983.最低票價

題目

在一個火車旅行很受歡迎的國度,你提前一年計劃了一些火車旅行。在接下來的一年裏,你要旅行的日子將以一個名爲 days
的數組給出。每一項是一個從 1 到 365 的整數。

火車票有三種不同的銷售方式:

一張爲期一天的通行證售價爲 costs[0] 美元; 一張爲期七天的通行證售價爲 costs[1] 美元; 一張爲期三十天的通行證售價爲
costs[2] 美元。 通行證允許數天無限制的旅行。 例如,如果我們在第 2 天獲得一張爲期 7 天的通行證,那麼我們可以連着旅行 7
天:第 2 天、第 3 天、第 4 天、第 5 天、第 6 天、第 7 天和第 8 天。

返回你想要完成在給定的列表 days 中列出的每一天的旅行所需要的最低消費。

示例 1:

輸入: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,並完成了你計劃的每一天旅行。 示例 2:

輸入:days = [1,2,3,4,5,6,7,8,9,10,30,31], costs = [2,7,15] 輸出:17 解釋:
例如,這裏有一種購買通行證的方法,可以讓你完成你的旅行計劃: 在第 1 天,你花了 costs[2] = $15 買了一張爲期 30
天的通行證,它將在第 1, 2, …, 30 天生效。 在第 31 天,你花了 costs[0] = $2 買了一張爲期 1
天的通行證,它將在第 31 天生效。 你總共花了 $17,並完成了你計劃的每一天旅行。

提示:

1 <= days.length <= 365 1 <= days[i] <= 365 days 按順序嚴格遞增 costs.length
== 3 1 <= costs[i] <= 1000

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/minimum-cost-for-tickets
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

分析

這道題目和上臺階、找零錢的問題有點像,可以採用動態規劃解決。
在第i天的時候,如果有出行計劃,需要比較的三種方案爲:

  1. dp[i-1]+cost[0];
  2. dp[i-7]+cost[1];
  3. dp[i-30]+cost[2];
    當中括號內數值爲負的時候dp取值爲0.
    如果沒有出行計劃,則直接由dp[i]=dp[i-1];

可以考慮加上一個類似“日曆”的數組,對應日期有出行計劃就置1否則置0.這樣直觀上比較容易理解和實現,而且對亂序的days也可以滿足。

代碼

int mincostTickets(int* days, int daysSize, int* costs, int costsSize){
    int dp[366]={0};
    int hash[366]={0};		//用於當作“日曆”
    for(int i=0;i<daysSize;i++)
        hash[days[i]]=1;
    for(int i=1;i<=365;i++){
        if(hash[i]==1){		//如果當日有出行計劃
            dp[i]=dp[i-1]+costs[0];		
            dp[i]=dp[i]<(dp[(i>=7?(i-7):0)]+costs[1])?dp[i]:(dp[(i>=7?(i-7):0)]+costs[1]);
            dp[i]=dp[i]<(dp[(i>=30?(i-30):0)]+costs[2])?dp[i]:(dp[(i>=30?(i-30):0)]+costs[2]);
        }else {
            dp[i]=dp[i-1];
        }
    }
    return dp[days[daysSize-1]];
}

運行結果

在這裏插入圖片描述
直接雙百了。其實講道理優化空間確實也不多,不過考慮到題目中給出的days數組是嚴格升序的,所以可以把“日曆”功能給去掉。

不使用“日曆功能”代碼

int mincostTickets(int* days, int daysSize, int* costs, int costsSize){
    int dp[366]={0};
    int index = 0;

    for(int i=1;i<=365;i++){
        if( i == days[index]){		//第i天有出行計劃
            dp[i]=dp[i-1]+costs[0];
            dp[i]=dp[i]<(dp[(i>=7?(i-7):0)]+costs[1])?dp[i]:(dp[(i>=7?(i-7):0)]+costs[1]);
            dp[i]=dp[i]<(dp[(i>=30?(i-30):0)]+costs[2])?dp[i]:(dp[(i>=30?(i-30):0)]+costs[2]);
            if (index < daysSize - 1){  //之後還有出行計劃
                index++;
            } else {
                return dp[i];	//之後沒有出行計劃就直接返回,後面就不用計算了
            }
        }else {
            dp[i]=dp[i-1];
        }
    }
    //return dp[days[daysSize-1]];
}

運行結果

在這裏插入圖片描述

在我意料之外,內存消耗居然增加了……???
講道理我少申請了一個數組空間,內存消耗應該減少纔對啊……我也不知道是什麼原因……我覺得可能是編譯過程的開銷,但是因爲我不瞭解平臺技術細節所以我也沒法做判斷。
如果知道原因的小夥伴可以留言告訴我~謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章