แหล่งอ้างอิง: https://cses.fi/book/book.pdf
แหล่งอ้างอิง: https://www.geeksforgeeks.org/greedy-algorithms/
โจทย์: ต้องการทอนเงินจำนวน ( n ) ด้วยจำนวนเหรียญที่น้อยที่สุด
แหล่งอ้างอิง: https://cses.fi/book/book.pdf
โจทย์: มีกิจกรรมที่มีเวลาเริ่มและสิ้นสุด ต้องการเลือกจำนวนกิจกรรมที่มากที่สุดโดยไม่ซ้อนทับกัน
แหล่งอ้างอิง: https://www.geeksforgeeks.org/activity-selection-problem-greedy-algo-1/
โจทย์: ได้คะแนน ( d - f ) โดย ( d ) คือเดดไลน์ และ ( f ) คือเวลาที่ทำเสร็จจริง
แหล่งอ้างอิง: https://cses.fi/book/book.pdf
แบ่งปัญหาใหญ่เป็นปัญหาย่อยที่ เป็นอิสระต่อกัน
แก้ปัญหาย่อยโดยใช้การเรียกซ้ำ (Recursion)
รวมคำตอบจากปัญหาย่อยเข้าด้วยกันเป็นคำตอบเดียว
ตัวอย่างเช่น: Merge Sort, Quick Sort, Binary Search
แหล่งอ้างอิง: https://www.geeksforgeeks.org/divide-and-conquer/
ใช้เมื่อการคำนวณหาคำตอบโดยตรงนั้นยาก แต่การ ตรวจสอบ (Check) ว่าค่าที่กำหนดให้นั้นเป็นไปได้หรือไม่นั้นทำได้ง่าย:
แหล่งอ้างอิง: https://usaco.guide/general/binary-search
ใช้ Binary Search หาจุดสูงสุดของฟังก์ชันที่เพิ่มขึ้นแล้วลดลง:
int x = -1;
for (int b = z; b >= 1; b /= 2) {
while (!ok(x+b)) x += b;
}
int k = x+1;
แนวคิดนี้ช่วยเปลี่ยนปัญหาการค้นหาเชิงเส้น ( O(n) ) ให้กลายเป็น ( O(\log n) ) โดยอาศัยสมบัติของฟังก์ชัน
แหล่งอ้างอิง: https://cses.fi/book/book.pdf
โจทย์: มีเส้นวัตถุดิบความยาวต่างๆ ต้องการตัดให้ได้ ( M ) ชิ้นที่ความยาวเท่ากัน ( x ) จงหา ( x ) ที่มากที่สุด
แหล่งอ้างอิง: https://cses.fi/book/book.pdf
เมื่อทำงานกับเลขทศนิยม (Floating point):
แหล่งอ้างอิง: https://cses.fi/book/book.pdf
การจะใช้ Binary Search on Answer ได้ ฟังก์ชันการตรวจสอบ ( (ok(x)) ) ต้องมีสมบัติเปลี่ยนผ่านเพียงครั้งเดียว:
แหล่งอ้างอิง: https://cses.fi/book/book.pdf
ฟังก์ชันตรวจสอบความถูกต้อง:
int countRods(vector<int> A, double x) {
int dogs = 0;
for (int l : A) dogs += (int)(l / x);
return dogs;
}
ในโจทย์นี้ ( countRods ) จะมีค่าลดลงเมื่อ ( x ) เพิ่มขึ้น (Monotonically Decreasing) เราจึงสามารถใช้ Binary Search เพื่อหาค่า ( x ) ที่มากที่สุดที่ยังทำให้ได้จำนวนชิ้น ( \ge M ) ตามต้องการได้
แหล่งอ้างอิง: https://github.com/usaco-guide/usaco-guide
แหล่งอ้างอิง: https://www.geeksforgeeks.org/merge-sort/
ใช้ลดความซับซ้อนของปัญหาประเภท Exponential เช่น ( O(2^n) ) ให้เหลือ ( O(2^{n/2}) ):
แหล่งอ้างอิง: https://cses.fi/book/book.pdf
โจทย์: หาเซตย่อยที่บวกกันได้ ( T ) จากเลข 40 ตัว
แหล่งอ้างอิง: https://www.geeksforgeeks.org/meet-in-the-middle/
ต้องการเลือกกิจกรรมที่ไม่ซ้อนทับกันให้ได้จำนวนมากที่สุด:
ความซับซ้อนคือ ( O(n \log n) ) จากการเรียงลำดับข้อมูล ซึ่งเร็วกว่าการใช้ DP ในโจทย์ประเภทนี้มาก
แหล่งอ้างอิง: https://cses.fi/book/book.pdf
เราจะมั่นใจได้อย่างไรว่า Greedy ของเราให้คำตอบที่ดีที่สุด (Optimal)?
แหล่งอ้างอิง: https://en.wikipedia.org/wiki/Greedy_algorithm
| หัวข้อ | Greedy | Dynamic Programming |
|---|---|---|
| การเลือก | เลือกสิ่งที่ดีที่สุด ณ ตอนนี้ทันที | ลองทุกทางเลือกที่เป็นไปได้ |
| ความซับซ้อน | มักจะต่ำมาก ( (O(n)) หรือ (O(n \log n)) ) | สูงกว่า (ขึ้นกับจำนวน State) |
| ความถูกต้อง | ต้องพิสูจน์ด้วยความยากลำบาก | รับประกันโดยธรรมชาติของการลองทุก State |
แหล่งอ้างอิง: https://www.geeksforgeeks.org/greedy-approach-vs-dynamic-programming/
15:00 - 17:00 น. ตะลุยโจทย์ Range Queries และ Optimization:
"ความรู้ทางทฤษฎีจะไร้ผล หากไม่ผ่านการเขียนโค้ดจริง"
หัวใจสำคัญที่เราได้รับในวันนี้:
"ถึงเวลาพักสมองสั้นๆ ก่อนเข้าสู่ช่วงลงมือทำจริงในลำดับถัดไป!"