Notes & software courses · Free to learn
Aph's Blog
On this page

Greedy Algorithms

👋 อ่านฟรีทั้งหมดบน Aph's Blog — เนื้อหาภาษาไทย ทำตามทีละหน้าใน sidebar ได้เลย หากมีข้อเสนอแนะหรืออยากให้เพิ่มหัวข้อไหน บอกได้เสมอ

แก้ปัญหาด้วยการเลือก "ดีที่สุดตอนนี้" ทุกขั้น — เร็วและง่าย แต่ต้องรู้ว่าเมื่อไรใช้ไม่ได้

greedy algorithm แก้ปัญหาด้วยการเลือกตัวเลือกที่ดีที่สุด ณ ตอนนั้นทุกขั้น โดยไม่ย้อนคิด เร็วและเขียนง่าย แต่ใช้ได้เฉพาะปัญหาบางแบบ — สำคัญที่ต้องรู้ว่าเมื่อไรใช้ได้และเมื่อไรไม่ได้

ตัวอย่าง: ทอนเงินจำนวนเหรียญน้อยสุด

เลือกเหรียญใหญ่สุดที่ใช้ได้ก่อนเสมอ — greedy ใช้ได้กับชุดเหรียญมาตรฐาน

python
def make_change(amount, coins):
    coins = sorted(coins, reverse=True)   # ใหญ่ไปเล็ก
    result = []
    for coin in coins:
        while amount >= coin:
            amount -= coin            # เลือกเหรียญใหญ่สุดที่ใช้ได้
            result.append(coin)
    return result

print(make_change(63, [1, 5, 10, 20]))   # [20,20,20,1,1,1]

ตัวอย่าง: activity selection

เลือกกิจกรรมให้ได้มากที่สุดโดยไม่ทับเวลากัน — greedy: เลือกตัวที่ "จบก่อน" เสมอ

python
def max_activities(activities):
    # activities = [(start, end), ...]
    activities.sort(key=lambda a: a[1])   # เรียงตามเวลาจบ
    count, last_end = 0, 0
    for start, end in activities:
        if start >= last_end:             # ไม่ทับ
            count += 1
            last_end = end
    return count

print(max_activities([(1, 3), (2, 5), (4, 6), (6, 8)]))   # 3

greedy ไม่ได้ผลเสมอ

บางปัญหา greedy ให้คำตอบผิด เช่นทอนเงินด้วยชุดเหรียญแปลก ๆ — ต้องใช้ DP แทน

python
# coins = [1, 3, 4], ทอน 6
# greedy: 4 + 1 + 1 = 3 เหรียญ  (ผิด!)
# คำตอบจริง: 3 + 3 = 2 เหรียญ  (DP หาเจอ)
greedy ต้องพิสูจน์ว่า 'ดีตอนนี้ → ดีรวม'

greedy ใช้ได้ก็ต่อเมื่อ "การเลือกดีที่สุดตอนนี้ นำไปสู่คำตอบที่ดีที่สุดโดยรวม" (greedy choice property) ถ้าไม่แน่ใจ อย่าเพิ่งเชื่อ greedy — ลองหา counterexample หรือใช้ DP เทียบ เพราะ greedy ที่ผิดจะดูเหมือนถูกในตัวอย่างง่าย ๆ

สรุปหัวข้อนี้

  • greedy = เลือกดีที่สุดตอนนี้ทุกขั้น ไม่ย้อนคิด — เร็ว เขียนง่าย
  • ใช้ได้: ทอนเงิน(ชุดมาตรฐาน), activity selection, interval
  • ไม่ได้เสมอ — บางปัญหาต้องใช้ DP (เช่นทอนเงินชุดแปลก)
  • ต้องมั่นใจว่า 'ดีตอนนี้ → ดีรวม' ก่อนใช้ greedy
แบบฝึกหัด

1) เขียนทอนเงินแบบ greedy 2) แก้ activity selection 3) หา counterexample ที่ greedy ทอนเงินผิด (coins=[1,3,4]) 4) อธิบาย greedy choice property ด้วยคำตัวเอง