Skip to content

Commit a62b187

Browse files
983 Minimum Cost For Tickets.py
1 parent 4a05627 commit a62b187

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed

983 Minimum Cost For Tickets.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#!/usr/bin/python3
2+
"""
3+
In a country popular for train travel, you have planned some train travelling
4+
one year in advance. The days of the year that you will travel is given as an
5+
array days. Each day is an integer from 1 to 365.
6+
7+
Train tickets are sold in 3 different ways:
8+
9+
a 1-day pass is sold for costs[0] dollars;
10+
a 7-day pass is sold for costs[1] dollars;
11+
a 30-day pass is sold for costs[2] dollars.
12+
The passes allow that many days of consecutive travel. For example, if we get
13+
a 7-day pass on day 2, then we can travel for 7 days: day 2, 3, 4, 5, 6, 7, and
14+
8.
15+
16+
Return the minimum number of dollars you need to travel every day in the given
17+
list of days.
18+
19+
Example 1:
20+
21+
Input: days = [1,4,6,7,8,20], costs = [2,7,15]
22+
Output: 11
23+
Explanation:
24+
For example, here is one way to buy passes that lets you travel your travel plan:
25+
On day 1, you bought a 1-day pass for costs[0] = $2, which covered day 1.
26+
On day 3, you bought a 7-day pass for costs[1] = $7, which covered days 3, 4, ..., 9.
27+
On day 20, you bought a 1-day pass for costs[0] = $2, which covered day 20.
28+
In total you spent $11 and covered all the days of your travel.
29+
Example 2:
30+
31+
Input: days = [1,2,3,4,5,6,7,8,9,10,30,31], costs = [2,7,15]
32+
Output: 17
33+
Explanation:
34+
For example, here is one way to buy passes that lets you travel your travel plan:
35+
On day 1, you bought a 30-day pass for costs[2] = $15 which covered days 1, 2, ..., 30.
36+
On day 31, you bought a 1-day pass for costs[0] = $2 which covered day 31.
37+
In total you spent $17 and covered all the days of your travel.
38+
39+
Note:
40+
41+
1 <= days.length <= 365
42+
1 <= days[i] <= 365
43+
days is in strictly increasing order.
44+
costs.length == 3
45+
1 <= costs[i] <= 1000
46+
"""
47+
from typing import List
48+
49+
50+
class Solution:
51+
def mincostTickets(self, days: List[int], costs: List[int]) -> int:
52+
"""
53+
Iterate backward.
54+
55+
Why does iterate backward work? Currrent min depends on the future mins
56+
57+
Let F[i] be the min cost at day i, covering all trips from i to 365
58+
F[i] = min(F[i + d] + c for d, c in zip([1, 7, 30], costs))
59+
If day i is not travel day, then wait until i + k that is a travel day
60+
61+
O(365)
62+
"""
63+
F = [float("inf") for _ in range(366 + 30)]
64+
for i in range(366, 366 + 30):
65+
F[i] = 0
66+
67+
days_set = set(days)
68+
for i in range(365, 0, -1):
69+
if i not in days_set:
70+
F[i] = F[i+1]
71+
else:
72+
F[i] = min(
73+
c + F[i+d]
74+
for d, c in zip([1, 7, 30], costs)
75+
)
76+
77+
return F[1]
78+
79+
def mincostTickets_error(self, days: List[int], costs: List[int]) -> int:
80+
"""
81+
Iterate backward on days
82+
O(30 * |days|)
83+
84+
Iterate throughout the year is more elegant
85+
Need buffer day
86+
"""
87+
n = len(days)
88+
F = [float("inf") for _ in range(n)]
89+
F[-1] = costs[0]
90+
for i in range(n-2, -1, -1):
91+
for j in range(i+1, n):
92+
delta = days[j] - days[i]
93+
if delta <= 1:
94+
F[i] = min(F[i], costs[0] + F[j])
95+
if delta <= 7:
96+
F[i] = min(F[i], costs[1] + F[j])
97+
if delta <= 30:
98+
F[i] = min(F[i], costs[2] + F[j])
99+
else:
100+
break
101+
return F[0]
102+
103+
def mincostTickets_error(self, days: List[int], costs: List[int]) -> int:
104+
"""
105+
dp
106+
Let F[i] be the min cost at day i, covering all trips from day 1 to i
107+
For 30-day ticiekt, iterate forward all 30 days?
108+
How to express idle date? Same as previous.
109+
110+
Why does iterate forward fail? Because future min does not depends on the
111+
current min. Current higher cost may contribtue to future lower cost.
112+
"""
113+
F = [float("inf") for _ in range(365 + 1)]
114+
F[0] = 0
115+
days_set = set(days)
116+
for i in range(1, 366):
117+
if i not in days_set:
118+
F[i] = F[i-1]
119+
else:
120+
# iterate forward does not work
121+
F[i] = min(F[i], F[i-1] + costs[0])
122+
123+
124+
if __name__ == "__main__":
125+
assert Solution().mincostTickets([1,4,6,7,8,20], [2,7,15]) == 11

0 commit comments

Comments
 (0)