มีวิธีแก้ปัญหาที่เร็วกว่าสำหรับปัญหา Great Wall Jam ของ Google Code หรือไม่


16

ลองพิจารณาคำถามรอบรหัส 1C ของ Google Jamต่อไปนี้:

กำแพงเมืองจีนเริ่มออกเป็นสายที่ไม่มีที่สิ้นสุดที่ความสูงในสถานที่ทั้งหมดเป็น00

ชนเผ่าจำนวนหนึ่ง ,จะโจมตีกำแพงตามพารามิเตอร์ต่อไปนี้ - วันเริ่มต้น, , กำลังเริ่มต้น , พิกัดทิศตะวันตกเริ่มต้น,และพิกัดทิศตะวันออกเริ่มต้น, . นี้การโจมตีครั้งแรกเกิดขึ้นในวันในช่วงที่แข็งแรงSหากมีส่วนใดของกำแพงภายในที่มีส่วนสูงการโจมตีจะสำเร็จและในตอนท้ายของวันกำแพงจะถูกสร้างขึ้นเพื่อให้ส่วนใดส่วนหนึ่งของมันภายในของความสูงนั้นจะอยู่ที่ความสูงยังไม่มีข้อความยังไม่มีข้อความ1000DSWD [ W , E ] S [ W , E ] < S [ W , E ] < S SED[W,E]S[W,E]<S[W,E]<SS (หรือมากกว่านั้นหากการโจมตีอื่น ๆ ในวันนั้นโจมตีกลุ่มเดียวกันด้วยความแข็งแกร่ง )S>S

แต่ละเผ่าจะทำการโจมตีได้มากถึงครั้งก่อนที่จะถอยออกไป ทุกเผ่ามี ,และที่กำหนดลำดับของการโจมตี: จะรอวันระหว่างการโจมตีพวกเขาจะย้ายช่วงการโจมตีหน่วยสำหรับการโจมตีแต่ละครั้ง (ลบ = ตะวันตกบวก = ตะวันออก) แม้ว่าขนาดของช่วงจะยังคงเหมือนเดิมและความแข็งแกร่งของพวกเขาจะเพิ่ม / ลดลงตามค่าคงที่หลังจากการโจมตีแต่ละครั้งδ D δ X δ S δ D1 δ X1000δDδXδSδD1δX

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

ฉันจัดการเพื่อเขียนรหัสโซลูชันที่ใช้งานได้ทำงานในประมาณ 20 วินาที: ฉันเชื่อว่าโซลูชันที่ฉันติดตั้งใช้เวลาเวลาโดยที่จำนวนการโจมตีทั้งหมดใน การจำลอง (สูงสุด ) และจำนวนทั้งหมดของจุดขอบที่ไม่ซ้ำกันในช่วงการโจมตี (สูงสุด )= 1000000 X =O(AlogA+(A+X)logX)A=1000000X=2000000

ในระดับสูงโซลูชันของฉัน:

  • อ่านข้อมูลเผ่าทั้งหมด
  • คำนวณ -coordinates ที่ไม่ซ้ำกันทั้งหมดสำหรับช่วงการโจมตี - O ( A )XO(A)
  • แสดง Wall เป็นต้นไม้ไบนารีที่ได้รับการปรับปรุงอย่างขี้เกียจในช่วงที่ติดตามค่าความสูงต่ำสุด leaf คือช่วงของพิกัดXสองจุดโดยไม่มีสิ่งใดอยู่ในระหว่างและโหนดพาเรนต์ทั้งหมดแสดงช่วงเวลาต่อเนื่องที่ครอบคลุมโดยลูก ๆ - O ( X log X )XXO(XlogX)
  • สร้างการโจมตีทั้งหมดที่ทุกเผ่าจะดำเนินการและเรียงลำดับตามวันที่ - O(AlogA)
  • สำหรับการโจมตีแต่ละครั้งดูว่าจะสำเร็จหรือไม่ ( เวลาการสืบค้นX ) เมื่อวันที่มีการเปลี่ยนแปลงวนลูปผ่านการโจมตีที่ประสบความสำเร็จทั้งหมดที่ยังไม่ได้ประมวลผลและปรับปรุงวอลล์ให้สอดคล้องกัน ( บันทึกเวลาอัพเดตXสำหรับการโจมตีแต่ละครั้ง) - O ( A log X )logXlogXO(AlogX)

คำถามของฉันคือ: มีวิธีที่จะทำได้ดีกว่าO(AlogA+(A+X)logX)หรือไม่? บางทีมีวิธีการเชิงกลยุทธ์ที่จะใช้ประโยชน์จากลักษณะเชิงเส้นของการโจมตีต่อเนื่องของชนเผ่าหรือไม่? 20 วินาทีรู้สึกยาวเกินไปสำหรับโซลูชันที่ตั้งใจไว้ (แม้ว่า Java อาจถูกตำหนิสำหรับเรื่องนั้น)


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

ฉันจะเก็บไว้เปิดแล้ว :)
torquestomp

คำตอบ:


2

ห้องพักที่ชัดเจนสำหรับการปรับปรุงคือขั้นตอนนี้:

สร้างการโจมตีทั้งหมดที่ทุกเผ่าจะดำเนินการและเรียงลำดับตามวันที่ - O(AlogA)

เรารู้ว่าชนเผ่าจะโจมตีจากวันใดวันหนึ่งเป็นระยะ นั่นหมายความว่าเราควรจะรวมรายการที่จัดเรียงไว้ล่วงหน้าเป็นจำนวนมาก คำแถลงปัญหาบอกเราว่าจะไม่มีเผ่ามากกว่า 1,000 เผ่า (เช่น 1,000 รายการที่จะรวม) จำนวนเล็กน้อยเมื่อเทียบกับการโจมตีสูงสุด 1,000,000 ครั้ง! การสลับนี้อาจลดเวลาการประมวลผลลงครึ่งหนึ่ง

นั่นคือทั้งหมดที่ฉันสามารถแนะนำสำหรับการเพิ่มประสิทธิภาพความซับซ้อนเชิงทฤษฎี แต่ฉันไม่มีข้อพิสูจน์ว่ามันจะดีที่สุดหลังจากการเปลี่ยนแปลงนี้


ฉันใช้ตัวต่อปริศนา แต่ฉันใช้ตัวอักษรเป็นตัวแทนของกำแพง: ต้นไม้ค้นหาแบบทวิภาค (C ++ std::mapเพื่อความแม่นยำ) จัดเก็บสถานที่ซึ่งความสูงของกำแพงเปลี่ยนไป ด้วยสิ่งนี้ฉันสามารถเพิ่มและลบโหนดได้ตามต้องการ (เช่นหากส่วนที่ซับซ้อนนั้นต้องเผชิญกับการโจมตีขนาดใหญ่ที่ท่วมท้นหรือการโจมตีหลายครั้งที่มีความแข็งแกร่งเท่ากันสัมผัสจำนวนโหนดจะลดลงอย่างมีนัยสำคัญ) วิธีนี้แก้ไขอินพุตขนาดใหญ่ใน 3.9 วินาที (บนแล็ปท็อปการพัฒนาข้อมูลจำเพาะกลางของฉัน) ฉันสงสัยว่ามีสาเหตุหลายประการสำหรับการปรับปรุง:

  • ตามที่คุณชี้ให้เห็นว่าการชกมวยและการเลิกทำกล่องอาจมีราคาแพง แต่ภาชนะบรรจุที่ใช้เทมเพลตของ C ++ จะหลีกเลี่ยงสิ่งนี้ทั้งหมด
  • ในขณะที่การแสดงผนังที่ฉันใช้นั้นแย่ลงในทางทฤษฎีในกรณีส่วนใหญ่ความสามารถในการลดจำนวนของโหนดทำให้มันเร็วขึ้นแบบไดนามิก . ในความเป็นจริงกรณีเดียวที่ใช้เวลาอย่างมีนัยสำคัญคือ # 7 ซึ่งดูเหมือนว่าได้ทำการทดสอบช่วงที่ไม่ได้ตัดกันมากมาย
  • ฉันไม่ได้ใช้การประมวลผลล่วงหน้า (ขั้นตอนจะพิจารณาจากการติดตามว่าแต่ละเผ่าจะโจมตีครั้งต่อไปเมื่อใดและค้นหาค่าร่วมต่ำสุดในแต่ละเทิร์น) อีกครั้งสิ่งนี้แย่กว่าทางทฤษฎี แต่สำหรับกรณีส่วนใหญ่ฉันสงสัยว่าค่าใช้จ่ายที่ต่ำกว่าหมายความว่ามันเร็วกว่า (ฉันจะทดสอบสิ่งนี้และกลับไปหาคุณ) อัปเดต : ฉันเพิ่มคิวลำดับความสำคัญสำหรับการโจมตีคล้ายกับวิธีที่อธิบายข้างต้น (แม้ว่าแทนที่จะสร้างอาร์เรย์ขนาดใหญ่ที่ฉันคำนวณแบบทันที) และเห็นเวลาลดลงเป็น 3.0 วินาทีสำหรับอินพุตขนาดใหญ่

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


1

ต่อไปนี้ถูกลบออกจากคำถามเนื่องจากเป็นคำตอบ

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

วิธีการแก้ปัญหาที่สามารถพบได้ที่นี่ มันเหมือนกับสิ่งที่ฉันโพสต์ไว้ที่นี่มาก ดังนั้นฉันมีแนวโน้มที่จะเชื่อว่าไม่มีวิธีแก้ปัญหาที่มีประสิทธิภาพมากขึ้น

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