Minimum Cost For Tickets

Updated on 09 June, 2025
Minimum Cost For Tickets header image

Problem Statement

You need to determine the minimum cost to purchase train tickets for a series of planned travel days within one calendar year. Each day you plan to travel is specified in an array called days, with elements ranging from 1 to 365. There are three types of train tickets available, each allowing a different range of consecutive travel days:

  • A 1-day pass costing costs[0] dollars.
  • A 7-day pass costing costs[1] dollars.
  • A 30-day pass costing costs[2] dollars.

You must use these ticket options to cover all the days you plan to travel and do so at the lowest possible cost.

Examples

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.

Constraints

  • 1 <= days.length <= 365
  • 1 <= days[i] <= 365
  • days is in strictly increasing order.
  • costs.length == 3
  • 1 <= costs[i] <= 1000

Approach and Intuition

When solving this problem, we should consider a few key insights and approaches, as demonstrated by the examples:

  1. Understand the options:

    • For each day that you need to travel, you have three ticket purchasing options:
      • Purchase a 1-day pass.
      • Purchase a 7-day pass.
      • Purchase a 30-day pass.
  2. Use Dynamic Programming:

    • You can use a dynamic programming approach to find the least cost to cover all the required travel days. Create an array dp where dp[i] holds the minimum cost to cover all travel up to day i.
  3. Iterate and decide:

    • For each travel day in days, decide which ticket is the most cost-effective to cover that day and potentially some days following it (depending on the duration of the ticket).
  4. Consider the sequence of travel days:

    • Rather than only focusing on each day independently, consider the sequence of days to make more strategic choices about which passes to buy.
  5. Optimize by Avoiding Unnecessary Coverage:

    • For days not in the days array, you shouldn't need any travel pass. Ensure that passes are bought primarily to cover only the days in the days list.
  6. Calculate Costs by Checking Conditions:

    • If buying a 7-day pass on a given day, check all the days this pass covers and calculate the total cost by adding the pass cost to dp of the day just before the pass starts. Repeat similarly for the 1-day and 30-day passes and choose the minimum resultant cost for each day.

The goal is to fill up dp[365] or dp[last travel day] if earlier, with the minimum spend required to cover all planned travel days. This involves iterating over each of the days in days, and at each day, considering if purchasing a new 1-day, 7-day, or 30-day pass will reduce the overall costs compared to previous strategies (dp values) already computed.

Solutions

  • C++
  • Java
cpp
class Solution {
public:
    int travelCostOptimizer(vector<int>& travelDays, vector<int>& ticketCosts) {
        int maxTravelDay = travelDays.back();
        vector<int> minCost(maxTravelDay + 1, 0);
        
        int travelIndex = 0;
        for (int currentDay = 1; currentDay <= maxTravelDay; currentDay++) {
            if (currentDay < travelDays[travelIndex]) {
                minCost[currentDay] = minCost[currentDay - 1];
            } else {
                travelIndex++;
                minCost[currentDay] = min({minCost[currentDay - 1] + ticketCosts[0],
                                           minCost[max(0, currentDay - 7)] + ticketCosts[1],
                                           minCost[max(0, currentDay - 30)] + ticketCosts[2]});
            }
        }
     
        return minCost[maxTravelDay];
    }
};

This solution focuses on determining the minimum cost to travel across a set number of days using a dynamic programming method. The function travelCostOptimizer takes two vectors as input: travelDays, which contains the specific days on which travel occurs, and ticketCosts, which represents the cost of different types of tickets that one can purchase. These ticket types cover single day, seven days, and thirty days of travel, respectively.

The approach involves creating a vector minCost where each index represents the minimum cost to travel up to that day. The algorithm iterates through each day, using previous computed values to determine the least cost for a given day either by using a single day pass, a seven day pass or a thirty day pass. If a particular day is not a travel day, then the cost remains the same as the previous day.

  • Steps to determine the minimum cost:
    1. Define maxTravelDay to find the last day of travel from travelDays.
    2. Initialize a vector minCost to store minimum costs up to each day, starting from zero up to maxTravelDay.
    3. Use a loop to fill minCost where for each day, consider if it is a travel day or not.
    4. If it is a travel day, compute the minimum cost by considering the cheapest option between buying a single day, seven days, or thirty days ticket.
    5. Return the value at maxTravelDay in minCost as the minimum cost required for the traveling days noted.

The function results in an efficient computation of the minimum traveling cost, leveraging past computed costs in a time-efficient manner using dynamic programming.

java
class Solution {
    public int minimumCostTravel(int[] travelDays, int[] passCosts) {
        // Identify the furthest day required for travel.
        int finalDay = travelDays[travelDays.length - 1];
        int travelCosts[] = new int[finalDay + 1];
        Arrays.fill(travelCosts, 0);

        int dayIndex = 0;
        for (int currentDay = 1; currentDay <= finalDay; currentDay++) {
            // Ensure costs are maintained on non-travel days.
            if (currentDay < travelDays[dayIndex]) {
                travelCosts[currentDay] = travelCosts[currentDay - 1];
            } else {
                // Progress to the next required travel day after ticket purchase.
                dayIndex++;
                // Calculate the most cost-effective ticket purchase.
                travelCosts[currentDay] = Math.min(travelCosts[currentDay - 1] + passCosts[0],
                        Math.min(travelCosts[Math.max(0, currentDay - 7)] + passCosts[1],
                                travelCosts[Math.max(0, currentDay - 30)] + passCosts[2]));
            }
        }

        return travelCosts[finalDay];
    }
}

For the problem titled "Minimum Cost For Tickets," the solution calculates the least expensive way to purchase travel passes based on specific travel days and the costs of three types of passes: 1-day, 7-day, and 30-day. The solution is implemented in Java.

Here's a breakdown of the solution approach:

  • Start by finding the last day in your input travelDays array, denoted as finalDay. This lets you know until which day you need to consider travel costs.
  • Create an array travelCosts sized to finalDay + 1, initializing all elements to zero. This array keeps track of the minimum travel costs accrued by each day up to finalDay.
  • Iterate over each day from 1 to finalDay. For days not in the travelDays array (non-travel days), copy the previous day's cost as no new pass is required.
  • On days you need to travel, decide which pass to buy by comparing the costs of continuing with a pass bought on an earlier day versus buying a new pass. This involves comparing costs as follows:
    • A new 1-day pass from the previous day's total cost plus the cost of the 1-day pass.
    • A new 7-day pass from the cost 7 days ago plus the cost of the 7-day pass; if less than 7 days have elapsed, compare from day 0.
    • A new 30-day pass from the cost 30 days ago plus the cost of the 30-day pass; if less than 30 days have elapsed, compare from day 0.
  • Store the minimum result of these compares in the travelCosts array.

By the end of the loop, travelCosts[finalDay] contains the minimum cost needed to cover all travel days efficiently. The dynamic programming approach ensures that each day is handled in an optimal way based on previous decisions, leading to an overall minimal travel expense.

Comments

No comments yet.