เมื่อใดที่ฉันจะใช้การเขียนโปรแกรมแบบไดนามิกเพื่อลดความซับซ้อนของเวลาของอัลกอริทึมแบบเรียกซ้ำ


13

การเขียนโปรแกรมแบบไดนามิกสามารถลดเวลาที่จำเป็นในการดำเนินการขั้นตอนวิธีแบบเรียกซ้ำ ฉันรู้ว่าการเขียนโปรแกรมแบบไดนามิกสามารถช่วยลดเวลาที่ซับซ้อนของอัลกอริทึม เงื่อนไขทั่วไปเช่นนั้นหรือไม่หากพอใจกับอัลกอริทึมแบบเรียกซ้ำจะบอกเป็นนัยว่าการใช้การเขียนโปรแกรมแบบไดนามิกจะช่วยลดความซับซ้อนของเวลาในอัลกอริทึมได้หรือไม่? ฉันควรใช้การเขียนโปรแกรมแบบไดนามิกเมื่อใด


คำตอบ:


9

การเขียนโปรแกรมแบบไดนามิกมีประโยชน์คืออัลกอริทึมแบบเรียกซ้ำของคุณพบว่าตัวเองเข้าถึงสถานการณ์เดียวกัน (พารามิเตอร์อินพุต) หลายครั้ง มีการแปลงทั่วไปจากอัลกอริธึมวนซ้ำเป็นการเขียนโปรแกรมแบบไดนามิกที่เรียกว่าการบันทึกความจำซึ่งมีตารางที่จัดเก็บผลลัพธ์ทั้งหมดที่เคยคำนวณโดยกระบวนการเรียกซ้ำของคุณ เมื่อเรียกขั้นตอนแบบเรียกซ้ำในชุดอินพุตที่ใช้ไปแล้วผลลัพธ์จะถูกดึงออกมาจากตาราง สิ่งนี้จะช่วยลด Fibonacci แบบเรียกซ้ำให้เท่ากับ Fibonacci ซ้ำ

การเขียนโปรแกรมแบบไดนามิกสามารถทำได้อย่างชาญฉลาดยิ่งขึ้นใช้การเพิ่มประสิทธิภาพที่เฉพาะเจาะจงมากขึ้น ตัวอย่างเช่นบางครั้งไม่จำเป็นต้องจัดเก็บตารางทั้งหมดในหน่วยความจำ ณ เวลาใดก็ตาม


ตัวนับจะเป็นว่าเมื่อใดก็ตามที่ความซับซ้อนของการบันทึกในพื้นที่มีค่ามากกว่าข้อมูลอินพุต (อาจเป็นเพียง> O (N)) โอกาสในการเขียนโปรแกรมแบบไดนามิกจะไม่ช่วย นั่นคือเมื่อคุณพบกับสถานการณ์เดียวกันนาน ๆ ครั้ง
edA-qa mort-ora-y

1
Memoisation! = การเขียนโปรแกรมแบบไดนามิก!
Raphael

1
ฉันไม่คิดว่าเรากำลังพูดถึงเรื่องนี้ แต่คำถามบ่งบอกถึงการลดความซับซ้อนของเวลา การเขียนโปรแกรมแบบไดนามิกด้วยตัวเองเพียงพาร์ทิชันปัญหา การเขียนโปรแกรมแบบไดนามิก + memoization เป็นวิธีทั่วไปเพื่อปรับปรุงความซับซ้อนเวลาที่เป็นไปได้
edA-qa mort-ora-y

@ edA-qamort-ora-y: ถูกต้อง ฉันคิดว่ามันเป็นสิ่งสำคัญที่จะต้องชี้ให้เห็นอย่างชัดเจนเนื่องจาก OP สับสน / ผสมผสานแนวคิด
กราฟิลส์

8

หากคุณเพียงแค่ต้องการเพิ่มความเร็วอัลกอริทึมแบบเรียกซ้ำของคุณการมีส่วนร่วมอาจเพียงพอ นี่เป็นเทคนิคการเก็บผลลัพธ์ของการเรียกใช้ฟังก์ชันเพื่อให้การโทรในอนาคตด้วยพารามิเตอร์เดียวกันสามารถนำผลลัพธ์มาใช้ใหม่ได้ สิ่งนี้ใช้ได้หาก (และเฉพาะในกรณี) ฟังก์ชั่นของคุณ

  • ไม่มีผลข้างเคียงและ
  • จะขึ้นอยู่กับพารามิเตอร์เท่านั้น (เช่นไม่ได้อยู่ในบางสถานะ)

มันจะช่วยให้คุณประหยัดเวลาถ้า (และถ้าหาก) ฟังก์ชั่นถูกเรียกด้วยพารามิเตอร์เดียวกันซ้ำแล้วซ้ำอีก ตัวอย่างที่ได้รับความนิยม ได้แก่ นิยามแบบเรียกซ้ำของตัวเลขฟีโบนักชีนั่นคือ

f(0)=0f(1)=1f(n+2)=f(n+1)+f(n), n0

ff(n)f(n+1)

โปรดทราบว่าในทางกลับกันการบันทึกข้อมูลนั้นไม่มีประโยชน์สำหรับอัลกอริธึมเช่นการเรียงแบบผสาน: โดยปกติรายการบางส่วนจะมีจำนวนเท่ากัน (ถ้ามี) และการตรวจสอบความเท่าเทียมกันนั้นมีราคาแพง (การเรียงลำดับ

ในการนำไปใช้งานจริงวิธีที่คุณเก็บผลลัพธ์นั้นมีการนำเข้าสู่ประสิทธิภาพอย่างยอดเยี่ยม การใช้ตารางแฮชอาจเป็นตัวเลือกที่ชัดเจน แต่อาจทำให้สถานที่แตกหัก หากพารามิเตอร์ของคุณไม่ใช่จำนวนเต็มแบบลบอาร์เรย์เป็นตัวเลือกที่เป็นธรรมชาติ แต่อาจทำให้เกิดค่าใช้จ่ายหน่วยความจำขนาดใหญ่หากคุณใช้เพียงบางรายการ ดังนั้นการบันทึกคือการแลกเปลี่ยนระหว่างผลกระทบและต้นทุน การจ่ายเงินนั้นขึ้นอยู่กับสถานการณ์เฉพาะของคุณหรือไม่


การเขียนโปรแกรมแบบไดนามิกเป็นสัตว์ร้ายอย่างสมบูรณ์ มันใช้ได้กับปัญหากับสถานที่นั้น ๆ

  • มันสามารถแบ่งเป็นปัญหาย่อย (อาจมีมากกว่าหนึ่งวิธี)
  • ปัญหาย่อยเหล่านั้นสามารถแก้ไขได้อย่างอิสระ
  • การแก้ปัญหา (ดีที่สุด) ของปัญหาย่อยเหล่านั้นสามารถรวมเข้ากับการแก้ปัญหาที่เหมาะสมที่สุดของปัญหาดั้งเดิมและ
  • ปัญหาย่อยมีคุณสมบัติเดียวกัน (หรือไม่สำคัญ)

นี้มักจะ (โดยปริยาย) โดยนัยเมื่อมีคนเรียกยามของหลักการ optimality

ทีนี้นี่เป็นเพียงการอธิบายปัญหาที่สามารถอธิบายได้ด้วยการเรียกซ้ำบางประเภท การประเมินผลเหล่านั้น (มัก) มีประสิทธิภาพเพราะสามารถนำไปใช้กับผลกระทบที่ดี (ดูด้านบน); โดยปกติปัญหาย่อยที่เล็กกว่าจะเกิดขึ้นเป็นส่วนหนึ่งของปัญหาที่ใหญ่กว่า ตัวอย่างที่นิยม ได้แก่การแก้ไขระยะทางและอัลกอริทึม Bellman ฟอร์ด


คุณกำลังพูดว่ามีบางกรณีที่การเขียนโปรแกรมแบบไดนามิกจะนำไปสู่ความซับซ้อนของเวลาที่ดีขึ้น แต่การบันทึกช่วยจำจะไม่ช่วย (หรืออย่างน้อยก็ไม่มาก)? คุณมีตัวอย่างหรือไม่? หรือคุณเพียงแค่บอกว่าการเขียนโปรแกรมแบบไดนามิกมีประโยชน์เฉพาะกับส่วนย่อยของปัญหาที่การจำคืออะไร?
svick

@svick: การเขียนโปรแกรมแบบไดนามิกไม่ได้เพิ่มความเร็วอะไรเลยต่อเมื่อมีการประเมินการเรียกซ้ำ DP ด้วย memoisation (ซึ่งโดยปกติคือ (!) ตัวพิมพ์เล็ก) อีกครั้ง: DP เป็นวิธีการสร้างแบบจำลองปัญหาในแง่ของการเรียกซ้ำ, memoisation เป็นเทคนิคในการเพิ่มความเร็วอัลกอริทึมแบบเรียกซ้ำที่เหมาะสม(ไม่ว่า DP) ไม่สมเหตุสมผลที่จะเปรียบเทียบทั้งสองโดยตรง แน่นอนว่าคุณพยายามจำลองปัญหาในฐานะ DP เพราะคุณคาดว่าจะใช้การบันทึกความจำและดังนั้นจึงแก้ปัญหาได้เร็วกว่าวิธีที่ไร้เดียงสา (r) แต่มุมมอง DP ไม่ได้นำไปสู่อัลกอริทึมที่มีประสิทธิภาพมากที่สุดเช่นกัน
กราฟิลส์

หากคุณมีโปรเซสเซอร์หลายตัวที่มีอยู่การเขียนโปรแกรมแบบไดนามิกช่วยปรับปรุงประสิทธิภาพของโลกแห่งความเป็นจริงอย่างมากเนื่องจากคุณสามารถทำขนานชิ้นส่วนได้ มันไม่ได้เปลี่ยนความซับซ้อนของเวลาจริง ๆ
edA-qa mort-ora-y

@ edA-qamort-ora-y: นั่นเป็นความจริงสำหรับการเรียกซ้ำใด ๆ อย่างไรก็ตามมันไม่ชัดเจนว่าสิ่งนี้จะสร้างการเร่งความเร็วที่ดีเพราะหน่วยความจำมีประสิทธิภาพน้อยกว่าขอบเขตของตัวประมวลผล
Raphael

การแก้ไข: การประเมินค่า DP ที่เกิดซ้ำอย่างไร้เดียงสายังคงสามารถเร็วกว่ากำลังดุร้าย (มาก) cf เลย ที่นี่
Raphael
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.