สร้างพาร์ติชันเวกเตอร์ทั้งหมดได้อย่างมีประสิทธิภาพ


12

พาร์ติชันเวกเตอร์แบ่งเวกเตอร์ขึ้นชุดของเวกเตอร์เพื่อให้ผลรวมของพวกเขาเป็นต้นฉบับ นี่คือพาร์ทิชันสอง:

[3, 1, 2] = [3, 1, 2]
[3, 1, 2] = [0, 0, 1] + [0, 0, 1] + [0, 1, 0] + [1, 0, 0] + [2, 0, 0]
[3, 1, 2] = [1, 1, 2] + [2, 0, 0]

การเพิ่มเวกเตอร์ที่นี่ทำองค์ประกอบที่ชาญฉลาด พาร์ติชันที่ถูกต้องไม่มีเวกเตอร์ใด ๆ ที่มีจำนวนเต็มลบหรือเวกเตอร์ทั้งหมดเป็นศูนย์

ตอนนี้ความท้าทายคือการเขียนโปรแกรมหรือฟังก์ชั่นที่สร้างพาร์ทิชันเวกเตอร์ที่เป็นไปได้ทั้งหมดที่กำหนดเวกเตอร์เป้าหมาย นี่อาจฟังดูง่าย ...

... แต่มีการบิด หากเวกเตอร์อินพุตมีขนาด L และพาร์ติชันที่ใหญ่ที่สุดที่สร้างขึ้นมีองค์ประกอบ M คุณไม่สามารถใช้หน่วยความจำ O (L * M) มากกว่า

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

[3, 1, 2] = [3, 0, 2] + [0, 1, 0]
[3, 1, 2] = [0, 1, 0] + [3, 0, 2]

หากคุณจะออกทั้งคำตอบของคุณไม่ถูกต้อง


พาร์ติชันทั้งหมดสำหรับ[3, 2]:

[3, 2]
[0, 1] + [3, 1]
[0, 1] + [0, 1] + [3, 0]
[0, 1] + [0, 1] + [1, 0] + [2, 0]
[0, 1] + [0, 1] + [1, 0] + [1, 0] + [1, 0]
[0, 1] + [1, 0] + [2, 1]
[0, 1] + [1, 0] + [1, 0] + [1, 1]
[0, 1] + [1, 1] + [2, 0]
[0, 2] + [3, 0]
[0, 2] + [1, 0] + [2, 0]
[0, 2] + [1, 0] + [1, 0] + [1, 0]
[1, 0] + [2, 2]
[1, 0] + [1, 0] + [1, 2]
[1, 0] + [1, 1] + [1, 1]
[1, 1] + [2, 1]
[1, 2] + [2, 0]

[3, 2, 5, 2]ในการทดสอบคำตอบของคุณทำงานบน มันควรสร้างพาร์ติชัน 17939 ซึ่งทั้งหมดรวม[3, 2, 5, 2]และที่ไม่ซ้ำกัน (คุณสามารถทดสอบความเป็นเอกลักษณ์โดยการเรียงลำดับแต่ละพาร์ติชันพจนานุกรม)


รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ

คำตอบ:


3

Python 2, 289 ไบต์

อัลกอริทึมแรงเดรัจฉานง่าย ถือว่ารายการทั้งหมดเป็นตัวเลขในฐานmax(input)+1( b) และตรวจสอบแต่ละ "หมายเลข" ในช่วง[0, b**(L*M))เพื่อดูว่า:

  1. ผลรวมถึงจำนวนที่ถูกต้อง
  2. เป็นไปตามลำดับตัวอักษร (สร้างความมั่นใจในความเป็นเอกลักษณ์)

หากรายการนั้นตรงกับเกณฑ์เหล่านี้โปรแกรมจะแสดงผลออกมาพร้อมกับเวกเตอร์ที่มีค่าเป็นศูนย์ทั้งหมดที่ถูกถอดออก

การใช้ความจำ

โครงสร้างข้อมูลที่ใหญ่ที่สุดที่ฉันใช้ในโปรแกรมนี้คือรายการซ้อนกันสองเท่าความยาวรายการMที่มีความยาว liss Lเพื่อให้O(L*M)หน่วยความจำ

สำหรับโครงสร้างข้อมูลอื่น ๆ ของฉันฉันมี 3 ints สากลO(3)ความยาว 1 รายการL( O(L)) ความยาว 1 อาร์เรย์M( O(M)) และสำเนาของอาร์เรย์ที่ใหญ่ที่สุดเมื่อส่งออก ( O(L*M))

ทั้งหมดนี้จะช่วยให้ฉันใช้หน่วยความจำของO(2*L*M + L + M + 3)ซึ่งช่วยลดความยุ่งยากในการO(L*M), fufilling เกณฑ์

ความซับซ้อนของเวลา

เป็นอัลกอริทึมกำลังดุร้ายอัลกอริทึมนี้ช้ามาก สำหรับวงในขณะที่จะลาออกจากการ int b-1สุดท้ายในความต้องการของอาร์เรย์จะเป็น การวนซ้ำต้องใช้b**(L*M)เวลาก่อนที่จะเกิดขึ้น

นอกจากนี้ทุกครั้งที่เรียกใช้รายการจะต้องตรวจสอบเงื่อนไขทั้งสองและพิมพ์รายการในกรณีที่เลวร้ายที่สุดโดยใช้L*M+L+Mการทำซ้ำ O(L*M * b**(L*M))นี้ง่ายที่จะให้โดยรวม ฉันพยายามทดสอบโปรแกรมของฉัน[3, 2, 5, 2]แต่ยอมแพ้หลังจาก 45 นาที

โปรแกรมกอล์ฟ

v=input()
L=len(v)
M=sum(v)
b=max(v)
R=range
t=[L*[0]for i in R(M)]
def A(l,i):
 if i<L*M-1and~-b<l[i/L][i%L]:A(l,i+1)
 l[i/L][i%L]=-~l[i/L][i%L]%-~b
while t[-1][-1]<b:
 if v==[sum(q[i]for q in t)for i in R(L)]and all(`t[i]`>=`t[i+1]`for i in R(M-1)):print[x for x in t if[0]*L!=x]
 A(t,0)

ฉันอาจจะเล่นกอล์ฟได้มากกว่านี้โดยเฉพาะส่วนที่เพิ่มขึ้น โค้ดที่ไม่ดีออกมา


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