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


273

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

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

เช่นว่า Ive ได้สี่เหลี่ยมดังต่อไปนี้

  • 128 * 32
  • 128 * 64
  • 64 * 32
  • 64 * 32

สามารถบรรจุลงในพื้นที่ 128 * 128

 _________________
| 128 * 32 |
| ________________ |
| 128 * 64 |
| |
| |
| ________________ |
| 64 * 32 | 64 * 32 |
| _______ | ________ |

อย่างไรก็ตามหากมี 160 * 32 และ 64 * 64 อันก็จะต้องใช้พื้นที่ 256 * 128

 ________________________________
| 128 * 32 | 64 * 64 | 64 * 32 |
| ________________ | | _______ |
| 128 * 64 | | 64 * 32 |
| | _______ | _______ |
| | |
| ________________ | ___ |
| 160 * 32 | |
| ____________________ | ___________ |

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


6
วิธีที่สองไม่ใช่วิธีที่ดีที่สุดใช่ไหม ไม่ควรเป็น 128 คูณ 224?
Mantas Vidutis

"ขนาดของพื้นที่นี้ควรเป็นพลังของทั้งสอง" ดังนั้นมันจึงไม่มีความแตกต่างสำหรับสิ่งนี้คือ / สำหรับฉันไม่สามารถสันนิษฐานว่าไม่ใช่พลังของสองได้รับการสนับสนุนโดยฮาร์ดแวร์พื้นฐาน
ไฟแลนเซอร์

2
อย่างไรก็ตามมันทำให้อัลกอริทึมง่ายขึ้นในที่สุด (ลองให้พอดีกับมันใน 32x32, ถ้า nto แล้วลอง 64x32, แล้ว 64x64, 128x64, ฯลฯ ) :)
ไฟ


ฉันวางวิธีการแก้ปัญหาเดรัจฉานแบบเดียวไว้ที่นี่stackoverflow.com/a/47698424/1641247
Sean

คำตอบ:


67

วิธีการแก้ปัญหาบัตรผ่านที่รวดเร็วและสกปรกนั้นเป็นวิธีที่ยอดเยี่ยมในการเริ่มต้นเสมอเป็นการเปรียบเทียบหากไม่มีสิ่งอื่นใด

โลภตำแหน่งจากใหญ่ไปเล็ก

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

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


1
ผมก็แค่เล่นกับสิ่งที่ต้องการในบิตของกระดาษในขณะนี้มีลักษณะเป็นธรรมที่ดีที่สุดในกรณีส่วนใหญ่ได้โดยไม่ต้องหมุนสี่เหลี่ยมหรืออะไร
ไฟแลนเซอร์

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

4
โซลูชันที่ดีที่สุดมีให้ในjair.org/media/3735/live-3735-6794-jair.pdf
Jim Balter

2
ฉันมีเวลายากที่จะจินตนาการว่าวิธีนี้สามารถทำงานได้ดีที่สุด ดังนั้นฉันเขียนมัน (มีรูปทรงสี่เหลี่ยม) และผลลัพธ์ที่ยอดเยี่ยม นี่เป็นอนิเมชั่นตัวอย่าง: imgur.com/ISjxuOR
Attila Tanyi

@JimBalter พื้นที่สี่เหลี่ยมฉลาด ... อาจ ... ในแง่ของความเร็วและความยืดหยุ่น? ไม่จริงเหรอ?
Arek Bal

86

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

นี่เป็นส่วนหนึ่งของอัลกอริทึม:

  1. อัลกอริธึมการลดความสูงแบบ First-Fit (FFDH)
    FFDH จะบรรจุรายการถัดไป R (ในระดับความสูงที่ไม่เพิ่ม) ในระดับแรกที่ R เหมาะสม หากไม่มีระดับที่สามารถรองรับ R ได้ระดับใหม่จะถูกสร้างขึ้น
    ความซับซ้อนของเวลาของ FFDH: O (n · log n)
    อัตราส่วนการประมาณ: FFDH (I) <= (17/10) · OPT (I) +1; ขอบเขตของซีมโทติค 17/10 นั้นแน่น

  2. อัลกอริธึมการลดความสูงของ Next-Fit (NFDH)
    NFDH จะบรรจุรายการถัดไป R (ในความสูงที่ไม่เพิ่ม) ในระดับปัจจุบันหาก R เหมาะกับ มิฉะนั้นระดับปัจจุบันคือ "ปิด" และระดับใหม่จะถูกสร้างขึ้น
    ความซับซ้อนของเวลา: O (n · log n)
    อัตราส่วนการประมาณ: NFDH (I) <= 2 · OPT (I) +1; ขอบเขตของซีมโทติค 2 แน่น

  3. อัลกอริธึมการลดความสูงที่ดีที่สุด (BFDH) ที่ดีที่สุด
    BFDH จะบรรจุรายการถัดไป R (ในระดับความสูงที่ไม่เพิ่มขึ้น) ในระดับที่สามารถรองรับ R ได้ซึ่งพื้นที่แนวนอนที่เหลือจะน้อยที่สุด หากไม่มีระดับที่สามารถรองรับ R ได้ระดับใหม่จะถูกสร้างขึ้น

  4. อัลกอริธึมล่างซ้าย (BL)
    รายการลำดับแรก BL โดยไม่เพิ่มความกว้าง BL แพ็ครายการถัดไปใกล้กับด้านล่างสุดเท่าที่จะพอดีจากนั้นใกล้กับด้านซ้ายสุดเท่าที่จะทำได้โดยไม่ทับซ้อนกับรายการที่บรรจุ โปรดทราบว่า BL ไม่ใช่อัลกอริธึมการบรรจุระดับ
    ความซับซ้อนของเวลา: O (n ^ 2)
    อัตราส่วนการประมาณ: BL (I) <= 3 · OPT (I)

  5. อัลกอริทึมของ Baker's Up-Down (UD)
    UD ใช้การรวมกันของ BL และการวางนัยทั่วไปของ NFDH ความกว้างของแถบและรายการจะถูกทำให้เป็นมาตรฐานเพื่อให้แถบนั้นมีความกว้างของหน่วย UD สั่งซื้อสินค้าในความกว้างที่ไม่เพิ่มขึ้นแล้วแบ่งรายการออกเป็นห้ากลุ่มแต่ละกลุ่มมีความกว้างในช่วง (1/2, 1], (1 / 3,1 / 2], (1 / 4,1 / 3) ], (1 / 5,1 / 4], (0,1 / 5] แถบจะแบ่งออกเป็นห้าภูมิภาค R1, ···, R5 โดยทั่วไปบางรายการของความกว้างในช่วง (1 / i + 1, 1 / i], สำหรับ 1 <= i <= 4, ถูกบรรจุในภูมิภาค Ri โดย BL เนื่องจาก BL ออกจากช่องว่างของการเพิ่มความกว้างจากบนลงล่างที่ด้านขวาของแถบ UD ใช้ประโยชน์นี้ก่อน บรรจุไอเท็มไปที่ Rj สำหรับ j = 1, ···, 4 (ตามลำดับ) จากบนลงล่างหากไม่มีที่ว่างเช่นนั้นไอเท็มจะถูกบรรจุลงใน Ri โดย BL ในที่สุดรายการที่มีขนาดสูงสุด 1/5 จะถูกบรรจุในพื้นที่ใน R1, ···, R4 โดยอัลกอริทึม NFDH (ทั่วไป)
    อัตราส่วนการประมาณ: UD (I) <= (5/4) · OPT (I) + (53/8) H โดยที่ H คือความสูงสูงสุดของรายการ ขอบเขตของซีมโทติค 5/4 นั้นแน่น

  6. อัลกอริทึมแบบย้อนกลับ (RF)
    RF ยังปรับความกว้างของแถบและรายการให้เป็นปกติเพื่อให้แถบมีความกว้างของหน่วย RF อันดับแรกจัดเรียงรายการทั้งหมดที่มีความกว้างมากกว่า 1/2 รายการที่เหลืออยู่จะถูกจัดเรียงในระดับความสูงที่ไม่เพิ่มขึ้นและจะถูกบรรจุไว้เหนือระดับความสูง H0 ซึ่งมากกว่า 1/2 จากนั้น RF จะทำซ้ำกระบวนการต่อไปนี้ โดยทั่วไปแล้ว RF จะบรรจุสิ่งของจากซ้ายไปขวาพร้อมด้านล่างตามความสูง H0 จนกว่าจะไม่มีที่ว่างอีกต่อไป จากนั้นแพ็ครายการจากขวาไปซ้ายและจากบนลงล่าง (เรียกว่าย้อนกลับระดับ) จนกระทั่งความกว้างรวมอย่างน้อย 1/2 จากนั้นระดับย้อนกลับจะลดลงจนกระทั่ง (อย่างน้อย) หนึ่งในนั้นแตะรายการด้านล่าง หล่นลงจะถูกทำซ้ำอย่างใด
    อัตราส่วนโดยประมาณ: RF (I) <= 2 · OPT (I)

  7. อัลกอริทึมของ Steinberg อัลกอริทึมของ
    Steinberg ซึ่งเขียนเป็น M ในกระดาษประเมินขอบเขตบนของความสูง H ที่จำเป็นในการบรรจุสิ่งของทั้งหมดเช่นที่พิสูจน์ว่ารายการอินพุตสามารถบรรจุในรูปสี่เหลี่ยมกว้าง W และความสูง H จากนั้นพวกเขา กำหนดเจ็ดโพรซีเดอร์ (โดยมีเงื่อนไขเจ็ดข้อ) แต่ละข้อแบ่งเป็นปัญหาเล็ก ๆ สองข้อและแก้ปัญหาแบบเรียกซ้ำ มันได้รับการแสดงให้เห็นว่าปัญหาที่เวิ้งว้างใด ๆ ตอบสนองหนึ่งในเจ็ดเงื่อนไข
    อัตราส่วนการประมาณ: M (I) <= 2 · OPT (I)

  8. อัลกอริทึมแบบแยกส่วน (SF) SF แบ่งรายการเป็นสองกลุ่ม L1 ที่มีความกว้างมากกว่า 1/2 และ L2 ไม่เกิน 1/2 รายการทั้งหมดของ L1 บรรจุโดย FFDH เป็นครั้งแรก จากนั้นจัดเรียงเพื่อให้รายการทั้งหมดที่มีความกว้างมากกว่า 2/3 ต่ำกว่ารายการที่มีความกว้างไม่เกิน 2/3 สิ่งนี้สร้างสี่เหลี่ยมผืนผ้า R ของพื้นที่ที่มีความกว้าง 1/3 รายการที่เหลือใน L2 จะถูกจัดเก็บใน R และพื้นที่ด้านบนที่บรรจุด้วย L1 โดยใช้ FFDH ระดับที่สร้างขึ้นใน R จะถือว่าต่ำกว่าระดับที่สร้างขึ้นเหนือการบรรจุของ L1
    อัตราส่วนการประมาณ: SF (I) <= (3/2) · OPT (I) + 2; ขอบเขตของซีมโทติค 3/2 นั้นแน่น

  9. อัลกอริทึมของ Sleator อัลกอริทึมของ
    Sleater ประกอบด้วยสี่ขั้นตอน:

    1. รายการที่มีความกว้างมากกว่า 1/2 ทั้งหมดจะถูกบรรจุไว้ที่ด้านบนของอีกด้านหนึ่งของแถบ สมมติว่า h0 คือความสูงของการบรรจุที่เกิดขึ้นการบรรจุที่ตามมาทั้งหมดจะเกิดขึ้นเหนือ h0

    2. รายการที่เหลืออยู่จะถูกเรียงลำดับตามความสูงไม่เพิ่ม ระดับของรายการจะถูกบรรจุ (ตามลำดับความสูงไม่เพิ่ม) จากซ้ายไปขวาตามแนวของความสูง h0

    3. จากนั้นเส้นแนวตั้งจะถูกวาดตรงกลางเพื่อตัดแถบเป็นสองส่วนเท่า ๆ กัน (หมายเหตุบรรทัดนี้อาจตัดรายการที่บรรจุบางส่วนในครึ่งขวา) วาดสองส่วนของเส้นนอนตามแนวนอนที่มีความยาวครึ่งหนึ่งส่วนหนึ่งข้ามครึ่งซ้าย (เรียกว่าเส้นฐานซ้าย) และอีกครึ่งหนึ่งของครึ่งด้านขวา (เรียกว่าเส้นฐานด้านขวา) ให้ต่ำที่สุดเท่าที่จะทำได้

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

    พื้นฐานใหม่จะเกิดขึ้นและขั้นตอน (4) ซ้ำบนพื้นฐานที่ต่ำกว่าจนกว่ารายการทั้งหมดจะถูกบรรจุ
    ความซับซ้อนของเวลา: O (n · log n)
    อัตราส่วนประมาณของอัลกอริทึมของ Sleator คือ 2.5 ซึ่งแน่น


6
สิ่งเหล่านี้จำเป็นต้องทราบความกว้างของพื้นที่
Quantum7

1
@ Quantum7 อาจไม่สำคัญเกินไปเนื่องจาก OP ต้องการด้านเป็นพลังของสองดังนั้นเราสามารถลองมิติที่มีพื้นที่เพียงพอ
Ciro Santilli 法轮功冠状病六四事件法轮功

19

มีลักษณะที่ปัญหาการบรรจุ ฉันคิดว่าคุณตกอยู่ภายใต้ 'ถังขยะ 2 มิติ' คุณควรเรียนรู้มากมายตั้งแต่วิธีแก้ปัญหาไปจนถึงปัญหาบรรจุภัณฑ์อื่น ๆ

ดูเพิ่มเติมที่: การบรรจุข้อมูลภาพสี่เหลี่ยมลงในพื้นผิวสี่เหลี่ยม


นี่เป็นอีกตัวอย่างที่ดีของอัลกอริทึมการบรรจุสี่เหลี่ยมผืนผ้าที่ปรับให้เหมาะสม: codeproject.com/Articles/210979/…
Anderson Green

ยังมีปัญหาที่กล่าวถึงใน: en.wikipedia.org/wiki/…นี้ จำกัด การบรรจุ bin ไว้ใน bin เดียวขนาดที่ไม่รู้จักฉันสงสัยว่ามันยังคง NP สมบูรณ์อยู่หรือไม่
Ciro Santilli 郝海东冠状病六四事件法轮功

17

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

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

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

สำหรับวงในของอัลกอริทึมของคุณ - อันที่ตอบว่า "ใช่" หรือ "ไม่" ไปยังกล่องที่มีขนาดเฉพาะฉันจะค้นหาการอ้างอิง Huang และเพียงใช้อัลกอริทึมของเขา เขามีการเพิ่มประสิทธิภาพจำนวนมากบนอัลกอริทึมพื้นฐาน แต่คุณต้องการเนื้อและมันฝรั่งพื้นฐานจริงๆเท่านั้น เนื่องจากคุณต้องการจัดการกับการหมุนทุกจุดของสาขาในระหว่างการค้นหาของคุณให้ลองทั้งการหมุนและการย้อนกลับเมื่อการหมุนทั้งสองไม่ทำให้เกิดปัญหา


9

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

ข่าวดีก็คือว่าเนื่องจากความจำเป็นในการแพ็คสี่เหลี่ยม 2 มิติในพื้นที่ จำกัด 2D คุณสามารถตัดความเป็นไปได้มากมายตั้งแต่เนิ่น ๆ ดังนั้นจึงอาจไม่เลวเลย


3
คุณอาจหมายถึง NP-complete
starblue

7
ทีนี้ถ้ามันเสร็จสมบูรณ์ NP มันก็ง่ายที่จะแก้เพียงแค่แก้ปัญหาตัวอย่างของพนักงานขายที่เดินทางแล้วคุณก็ไป แต่มันเป็นเรื่องเล็กน้อยที่จะแสดงให้เห็นว่าไม่ถูกต้องเนื่องจากปัญหาที่สมบูรณ์แบบของ NP เป็นปัญหาในการตัดสินใจ (คุณจะตอบกลับใช่ / ไม่ใช่คำตอบ) และมีอัลกอริทึมการยืนยันเวลาพหุนาม คำถาม "จะมีการจัดเรียงของสี่เหลี่ยม, B, C ... ที่ใช้พื้นที่น้อยกว่า 256 * 128 อาจจะ NP-สมบูรณ์.
คราส

2
@Eclipse ถูกต้อง จากjair.org/media/3735/live-3735-6794-jair.pdf "ปัญหาการหาค่าเหมาะที่สุดคือ NP-hard ในขณะที่ปัญหาในการตัดสินใจว่าชุดสี่เหลี่ยมสามารถบรรจุในกล่องที่กำหนดขอบเขตได้หรือไม่ ผ่านการลดขนาดจากถังขยะ (Korf, 2003) " อย่างไรก็ตามโปรดทราบว่า OP ขอให้ "วิธีที่เหมาะสมที่สุด" และมีวิธีแก้ปัญหาสำหรับ P ในคำจำกัดความกว้าง ๆ ของคำว่า "เป็นธรรม"
Jim Balter

ฉันยังสงสัยว่า NP-hardness แต่เราต้องการการอ้างอิง / หลักฐาน
Ciro Santilli 郝海东冠状病六四事件法轮功

2
necro ด้ายศักดิ์สิทธิ์แบทแมน นี่เป็นปัญหาการบรรจุและได้รับการพิสูจน์แล้วว่าดีที่สุดสำหรับ NP: en.wikipedia.org/wiki/Packing_problems
Blindy

2

สิ่งที่คุณต้องการคือ https://github.com/nothings/stb/blob/master/stb_rect_pack.h

ตัวอย่าง:

stbrp_context context;

struct stbrp_rect rects[100];

for (int i=0; i< 100; i++)
{
    rects[i].id = i;
    rects[i].w = 100+i;
    rects[i].h = 100+i;
    rects[i].x = 0;
    rects[i].y = 0;
    rects[i].was_packed = 0;
}

int rectsLength = sizeof(rects)/sizeof(rects[0]);

int nodeCount = 4096*2;
struct stbrp_node nodes[nodeCount];


stbrp_init_target(&context, 4096, 4096, nodes, nodeCount);
stbrp_pack_rects(&context, rects, rectsLength);

for (int i=0; i< 100; i++)
{
    printf("rect %i (%hu,%hu) was_packed=%i\n", rects[i].id, rects[i].x, rects[i].y, rects[i].was_packed);
}

1

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

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