1. 程式人生 > 實用技巧 >983. Minimum Cost For Tickets

983. Minimum Cost For Tickets

In a country popular for train travel, youhave planned some train travelling one year in advance. The days of the year that you will travel is given as an arraydays. Each day is an integer from1to365.

Train tickets are sold in 3 different ways:

  • a 1-day pass is sold forcosts[0]dollars;
  • a 7-day pass is sold forcosts[1]
    dollars;
  • a 30-day pass is sold forcosts[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 ofdays

.

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.

Example 2:

Input: days = [1,2,3,4,5,6,7,8,9,10,30,31], costs = [2,7,15]
Output: 17
Explanation: 
For example, here is one way to buy passes that lets you travel your travel plan:
On day 1, you bought a 30-day pass for costs[2] = $15 which covered days 1, 2, ..., 30.
On day 31, you bought a 1-day pass for costs[0] = $2 which covered day 31.
In total you spent $17 and covered all the days of your travel.

Note:

  1. 1 <= days.length <= 365
  2. 1 <= days[i] <= 365
  3. daysis in strictly increasing order.
  4. costs.length == 3
  5. 1 <= costs[i] <= 1000
class Solution {
    public int mincostTickets(int[] days, int[] costs) {
        int[] dp = new int[366];
        dp[0] = 0;
        boolean[] travel = new boolean[366];
        for(int i: days) travel[i] = true;
        for(int i = 1; i <= 365; i++) {
            if(!travel[i]) {
                dp[i] = dp[i-1];
                continue;
            }
            for(int j = 0; j < costs.length; j++) {
                if(i >= costs[j]) dp[i] = Math.min(dp[i], dp[i - costs[j]] + costs[j]);
            }
        }
        return dp[365];
    }
}

一開始啊,我這麼寫,我尋思妹啥毛病啊,結果不對

後來一想,這麼寫的話會導致買不到票,也就是第一天也買不到票,因為dp[i] = 0。所以要換個方法能讓前幾天買到票

class Solution {
    public int mincostTickets(int[] days, int[] costs) {
        int[] dp = new int[366];
        dp[0] = 0;
        boolean[] travel = new boolean[366];
        for(int i: days) travel[i] = true;
        for(int i = 1; i <= 365; i++) {
            if(!travel[i]) {
                dp[i] = dp[i-1];
                continue;
            }
            dp[i] = Integer.MAX_VALUE;
            dp[i] = Math.min(dp[i], dp[Math.max(0, i - 1)] + costs[0]);
            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[365];
    }
}

首先,dp【i】表示在第i天玩的時候最小要花費多少來買票,如果當前天數不在travel的days,那就讓他等於前一日的cost

上面Math.max(0, i - 1/7/30)就保證了所有天都能買到票。意思是在三種可能的情況下挑一個花費最小的

https://www.youtube.com/watch?v=BgWDlQy5JR0