서로 다른 크기의 사각형을 가능한 가장 작은 사각형으로 압축하는 데 어떤 알고리즘을 사용할 수 있습니까?


273

가능한 한 가장 작은 공간에 포장 해야하는 직사각형 객체가 많이 있습니다 (이 공간의 크기는 2의 거듭 제곱이어야합니다).

항목을 가능한 한 주어진 공간에 포장하는 다양한 포장 알고리즘을 알고 있지만이 경우 공간이 얼마나 커야하는지 알고리즘이 필요합니다.

예를 들어 다음 사각형이 있다고 가정 해보십시오.

  • 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 x 224가 아니어야합니까?
Mantas Vidutis

"이 공간의 크기는 2의 거듭 제곱이어야합니다."따라서 차이가 없습니다. 이것이 무엇인지 / 난 두 가지의 거듭 제곱이 기본 하드웨어에 의해 무조건적으로 지원된다고 가정 할 수는 없습니다.
Fire Lancer

2
어쨌든 그것은 결국 알고리즘을 더 간단하게 만들었습니다 (32x32에서 모두 맞추려면 64x32, 64x64, 128x64 등을 시도하십시오) :)
Fire Lancer


한 가지 유형의 무차별 대입 솔루션을 여기에 넣었습니다. stackoverflow.com/a/47698424/1641247
Sean

답변:


67

빠르고 더러운 첫 번째 패스 솔루션은 다른 방법이 없다면 비교해 보는 것이 좋습니다.

욕심 배치가 큰 것에서 작은 것.

가장 큰 직사각형을 포장 된 영역에 넣습니다. 어디에도 맞지 않을 경우 가능한 한 팩 영역을 확장하는 곳에 배치하십시오. 가장 작은 사각형으로 끝날 때까지 반복하십시오.

전혀 완벽하지는 않지만 쉽고 좋은 기준입니다. 그것은 여전히 ​​원래의 예를 완벽하게 포장하고 두 번째에 대해서도 동등한 대답을 줄 것입니다.


1
난 그냥 종이에 그런 것을 가지고 놀았는데, 사각형이나 다른 것을 회전시키지 않아도 대부분의 경우에 상당히 최적 인 것처럼 보입니다.
Fire Lancer

1
나는 그것을 구현하고 그것을 통해 많은 테스트 데이터를 실행했는데, 약간의 낭비 된 데이터 만 남기고 꽤 좋은 일을하는 것처럼 보입니다. 이제 사용 가능한 공간을 통해 각 rect에 대한 선형 검색보다 효율적인 구현을 다시 작성해야합니다. 각 픽셀이 (기존 rect에 대해) 차단되었는지 확인하십시오 ...
Fire Lancer


2
나는 이것이 어떻게 최적 일지를 상상하려고 애썼다. 그래서 (정사각형 모양으로) 코딩했으며 결과는 훌륭합니다. 다음은 데모 애니메이션입니다 : imgur.com/ISjxuOR
아틸라 Tanyi

@JimBalter 정사각형 공간 ... 아마도 ... 속도와 확장 성 측면에서? 그렇지 않습니까?
Arek Bal

86

솔루션에 대한 설문 조사 는 ARC 프로젝트에서이 페이지를 참조하십시오. 구현 복잡성 / 시간과 최적 성 사이에는 상충 관계가 있지만 선택할 수있는 광범위한 알고리즘이 있습니다.

알고리즘의 추출은 다음과 같습니다.

  1. FFDH (First-Fit 감소 높이) 알고리즘
    FFDH는 R이 맞는 첫 번째 레벨에서 다음 항목 R (증가하지 않는 높이)을 압축합니다. R을 수용 할 수있는 레벨이 없으면 새 레벨이 작성됩니다.
    FFDH의 시간 복잡도 : O (n · log n).
    근사 비율 : FFDH (I) <= (17/10) · OPT (I) +1; 17/10의 점근 적 경계는 빡빡합니다.

  2. NFDH (Next-Fit Decreeasing Height) 알고리즘
    NFDH는 R이 맞는 경우 다음 레벨 R을 현재 레벨에서 증가하지 않는 높이로 압축합니다. 그렇지 않으면 현재 레벨이 "닫히고"새 레벨이 작성됩니다.
    시간 복잡도 : O (n · log n).
    근사 비율 : NFDH (I) <= 2 · OPT (I) +1; 2의 점근 적 경계는 빡빡합니다.

  3. BFDH (Best-Fit Decineasing Height) 알고리즘
    BFDH는 R을 수용 할 수있는 나머지 수평 공간이 최소 인 다음 항목 R (증가하지 않는 높이)을 레벨에 패킹합니다. R을 수용 할 수있는 레벨이 없으면 새 레벨이 작성됩니다.

  4. 왼쪽 아래 (BL) 알고리즘
    BL 첫 번째 항목은 비 증가 너비로 주문합니다. BL은 포장 된 품목과 겹치지 않고 다음 품목을 바닥에 가깝게 포장 한 다음 왼쪽에 가깝게 포장합니다. BL은 레벨 지향 패킹 알고리즘이 아닙니다.
    시간 복잡도 : O (n ^ 2).
    근사 비율 : BL (I) <= 3 · OPT (I).

  5. 베이커 업다운 (UD) 알고리즘
    UD는 BL과 NFDH의 일반화의 조합을 사용합니다. 스트립 및 아이템의 폭은 스트립이 단위 폭이되도록 정규화된다. UD는 항목을 증가하지 않는 너비로 주문한 다음 항목을 너비가 (1/2, 1], (1 / 3,1 / 2], (1 / 4,1 / 3) 인 5 개의 그룹으로 나눕니다. ], (1 / 5,1 / 4], (0,1 / 5]. 스트립은 또한 5 개의 영역 R1, ···, R5로 나뉘며 기본적으로 (1 / i + 범위의 일부 항목) 1 <= i <= 4의 경우 1, 1 / i]는 영역 Ri에 BL로 패킹됩니다 .BL은 스트립의 오른쪽에서 위쪽에서 아래쪽으로 너비가 증가하는 공간을 남겨두기 때문에 UD는 먼저이 이점을 활용합니다. j = 1, ···, 4 (순서대로)부터 Rj까지 물품을 포장하는 경우 이러한 공간이없는 경우 물품은 BL로 Ri로 포장됩니다. 마지막으로 크기가 최대 1/5 인 물품 (일반화 된) NFDH 알고리즘에 의해 R1, ··· R4의 공간에 압축됩니다.
    근사 비율 : UD (I) <= (5/4) · OPT (I) + (53/8) H. 여기서 H는 품목의 최대 높이입니다. 5/4의 점근 적 경계는 빡빡합니다.

  6. RF (Reverse-fit) 알고리즘
    RF는 또한 스트립의 너비와 항목을 정규화하여 스트립이 단위 너비가되도록합니다. RF는 먼저 1/2보다 큰 너비의 모든 항목을 쌓습니다. 나머지 항목은 높이가 아닌 높이로 정렬되며 높이가 H0에 도달하면 1/2보다 큰 값으로 포장됩니다. 그런 다음 RF는 다음 프로세스를 반복합니다. 대략적으로 말하면 RF는 더 이상 공간이 없을 때까지 높이 H0 라인을 따라 하단에서 왼쪽에서 오른쪽으로 항목을 포장합니다. 그런 다음 전체 너비가 1/2 이상이 될 때까지 항목을 오른쪽에서 왼쪽으로, 위에서 아래로 (역 레벨이라고 함) 포장합니다. 그런 다음 리버스 레벨은 (적어도) 그들 중 하나가 아래의 일부 항목에 닿을 때까지 드롭 다운됩니다. 드롭 다운이 어떻게 든 반복됩니다.
    근사 비율 : RF (I) <= 2 · OPT (I).

  7. Steinberg의 알고리즘
    논문에서 M으로 표시된 Steinberg의 알고리즘은 모든 항목을 포장하는 데 필요한 높이 H의 상한을 추정하여 입력 항목을 너비 W와 높이 H의 사각형으로 포장 할 수 있음을 증명합니다. 문제를 두 개의 작은 문제로 나누고 재귀 적으로 해결하는 7 가지 절차 (7 가지 조건)를 정의합니다. 다루기 힘든 문제는 7 가지 조건 중 하나를 만족시키는 것으로 나타났습니다.
    근사 비율 : M (I) <= 2 · OPT (I).

  8. SF (Split-Fit algorithm) SF는 항목을 너비가 1/2보다 큰 L1과 최대 1/2 인 L2의 두 그룹으로 나눕니다. L1의 모든 품목은 먼저 FFDH에 의해 포장됩니다. 그런 다음 너비가 2/3 이상인 모든 항목이 너비가 2/3 이하인 항목보다 아래에 배치됩니다. 너비 1/3의 공간으로 직사각형 R을 만듭니다. 그런 다음 L2의 나머지 항목은 R로 패킹되고 FFDH를 사용하여 L1으로 패킹 된 것 위의 공간이 패킹됩니다. 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
OP는 측면이 2의 거듭 제곱이 필요하기 때문에 @ Quantum7은 그다지 중요하지 않으므로 충분한 면적으로 여러 차원을 시도해 볼 수 있습니다.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

19

포장 문제를 살펴보십시오 . 나는 당신이 '2D 빈 포장'에 속한다고 생각합니다. 솔루션에서 그와 다른 포장 문제에 이르기까지 많은 것을 배울 수 있어야합니다.

직사각형 이미지 데이터를 정사각형 텍스처로 패킹하기도 참조하십시오 .


최적화 된 사각형 패킹 알고리즘의 또 다른 좋은 예가 있습니다 : codeproject.com/Articles/210979/…
Anderson Green

또한 en.wikipedia.org/wiki/ 에서 언급 된 문제입니다. 특히, 이것은 빈 포장을 알 수없는 크기의 단일 빈으로 제한합니다. 그래도 NP가 완전하지 않은지 궁금합니다.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

17

이 문제에 대한 광범위한 문헌이 있습니다. 욕심 많은 휴리스틱은 컨테이너의 맨 아래와 왼쪽을 향한 첫 번째 사용 가능한 위치에서 가장 큰 영역에서 가장 작은 사각형으로 사각형을 배치하는 것입니다. 중력이 모든 항목을 왼쪽 아래 모서리로 당기는 것을 생각하십시오. 이 구글 "Chazelle 하단 왼쪽 포장"에 대한 설명.

최적의 솔루션을 위해 최첨단 기술은 몇 초 안에 20 개 이상의 직사각형을 포장 할 수 있습니다. Huang은 가장 작은 엔 클로징 경계 상자를 찾는 문제와 사각형 세트가 특정 크기의 경계 상자에 맞는지 여부를 결정하는 문제를 분리 하는 알고리즘 을 가지고 있습니다. 당신은 그의 프로그램에 직사각형 세트를 주었고, 그것들을 포장하는데 필요한 가장 작은 둘러싸는 경계 상자를 알려줍니다.

귀하의 경우 외부 루프는 가능한 가장 작은 경계 상자에서 위로 반복해야합니다 (폭과 높이가 2의 거듭 제곱에 따라 연속적으로 증가 함). 이 경계 상자 각각에 대해 사각형의 패킹을 찾을 수 있는지 테스트하십시오. 첫 번째 "예"답변이 나올 때까지 많은 "아니오"답변을 얻을 수 있으며 이는 최적의 솔루션이 될 것입니다.

특정 크기의 경계 상자에 "예"또는 "아니오"로 응답하는 알고리즘의 내부 루프의 경우 Huang 참조를 찾아 알고리즘을 구현합니다. 그는 기본 알고리즘 위에 많은 최적화를 포함하지만 기본 고기와 감자 만 있으면됩니다. 회전을 처리하려면 검색 중 모든 분기 지점에서 회전이 모두 해결되지 않으면 회전과 역 추적을 모두 시도하십시오.


9

나는 이것이 NP-hard 문제 라고 확신합니다. . 따라서 최적의 솔루션을 얻으려면 가능한 모든 조합을 시도하는 역 추적 알고리즘을 구현해야합니다.

좋은 소식은 제한된 2D 공간에 2D 직사각형을 포장해야하기 때문에 초기에 많은 가능성을 정리할 수 있으므로 그렇게 나쁘지 않을 수 있습니다.


3
아마도 NP- 완료를 의미 할 것입니다.
starblue

7
NP가 완료되면 해결하기 쉽고 여행하는 세일즈맨의 동등한 인스턴스를 해결하면됩니다. 그러나 NP 완료 문제가 의사 결정 문제 (예 / 답이 없음)이며 다항식 시간 검증 알고리즘을 가지고 있기 때문에 그렇지 않다는 것을 보여주는 것은 사소한 일입니다. 256 * 128보다 적은 면적을 차지하는 사각형 a, b, c ...의 배열이 NP-complete 일 수 있다는 문제가 있습니다.
Eclipse

2
@Eclipse가 정확합니다. 에서 jair.org/media/3735/live-3735-6794-jair.pdf 사각형의 세트가 주어진 경계 상자에 포장 할 수 있는지 여부를 결정하는 문제는 NP-완료하면서 "최적화 문제는, NP-어렵다 빈 포장을 줄임으로써 (Korf, 2003). " 그러나 OP는 "상당히 최적의 방법"을 요구했으며, "공정하게"의 광범위한 정의를 위해 P에는 그에 대한 솔루션이 있습니다.
Jim Balter 2016 년

또한 NP 경도를 의심하지만 참조 / 증거가 필요합니다.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

2
거룩한 실 네크로, 배트맨. 이것은 패킹 문제이며, 이미 NP-hard 인 것으로 이미 입증되었습니다 : 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.