Tossaporn Saengja

Dynamic Programming

หลักการ

ปัญหาการทอนเหรียญ (ปัญหาเดียวกับ Greedy)

พิจารณาปัญหาที่ต้องการทอนเงินมูลค่า nn โดยใช้เหรียญที่มีมูลค่า {c1,c2,,ck}\{c_1, c_2, \cdots, c_k\} จำนวนเหรียญที่น้อยที่สุดที่ต้องใช้เป็นเท่าไร?

หากมูลค่าของเหรียญเป็น

{1,3,4}\{1,3,4\}

มูลค่ารวม nn จำนวนเหรียญที่น้อยที่สุด
0 0
1 1
2 2
3 1
4 1
5 2
6 2
7 2
8 2
9 3
10 3

นิยาม dnd_n ให้เก็บค่าแทนจำนวนเหรียญที่น้อยที่สุดที่ใช้ทอนเงินมูลค่า nn

จะได้ว่า

di=min(di1+1,di3+1,di4+1)d_i = \min{(d_{i-1}+1, d_{i-3}+1, d_{i-4}+1)}

ซึ่งเป็น recursive case โดย base case คือ d0=0d_0 = 0

Longest Increasing Subsequence

https://cp-algorithms.com/sequences/longest_increasing_subsequence.html

Review

คืออะไร?

มีอะไรบ้าง?

example

fibonacci

f(n)=f(n1)+f(n2)f(n) = f(n-1) + f(n-2)

for (i: 2 → n) dp[i] = dp[i-1] + dp[i-2]

LIS

หาลำดับย่อยที่ยาวที่สุดที่เป็น increasing subsequence

1 5 3 2 8 9 3 6 → 1 2 3 6 / 1 2 8 9 / 1 5 8 9 / == 4

N2N^2 solution:

define state: dp[i] = ความยาวสูงสุดของ increasing subsequence เมื่อพิจารณาช่องที่ 0-i แล้วลงท้ายด้วยเลข a[i]

คำตอบสุดท้าย max(dp[1:N])

update state: new input: x, พิจารณา a[j]<xa[j] < x, แล้วเก็บค่า dp[i]=max(dp[j]+1)dp[i] = max(dp[j]+1)

backtrack: + ให้เก็บด้วย j เป็นเท่าไร

     0 1 2 3 4 5 6 7 8

a  : 1 5 3 2 8 9 3 6
dp : 0 1 2 2 2 3 4 3 4
bt : 0 0 1 1 1 4 5 4 7

NlogNN \log{N} solution:

define state: dp[i] = ค่าที่น้อยที่สุดที่เป็นค่าสุดท้ายของ increasing subsequence ความยาว i

update state: new input: x ไล่ตั้่งแต่ dp[j: 0 → mx]

คำตอบสุดท้าย mx

dp[0] = 0 
dp[1] = 1
dp[2] = 2
dp[3] = 3
dp[4] = 6
dp[5] =

เพิ่มเติม