2D 배열에서 모양 찾기 및 최적화


11

방금 이미지가 허용되었습니다 ... 게임에서 아래 이미지는 "T"모양의 일부로 인식 된 어두운 블록을 보여줍니다. 알 수 있듯이 코드는 빨간 점으로 블록을 어둡게하고 녹색 윤곽선으로 "T"모양을 보지 못했습니다.

원하는 패턴을 찾았지만 아직 최적화되지 않았습니다

내 코드는 x / y를 반복하고, 사용 된대로 블록을 표시하고, 모양을 회전하고, 반복하고, 색상을 변경하고, 반복합니다.

나는이 확인을 큰 떨림으로 고치기 시작했습니다. 현재 아이디어는 다음과 같습니다.

  • 그리드를 반복하고 모든 패턴 어커런스를 기록하고 (사용 된대로 마킹하지 않음)이를 어레이에 배치
  • 어떤 블록이 어떤 패턴에 의해 점유되는지, 따라서 어떤 패턴이 여러 패턴에 의해 점유되는지를 주목하면서, 그리드를 다시 루프한다.
  • 그리드를 다시 반복하면서 이번에는 어떤 패턴이 어떤 패턴을 방해하는지 주목

기분이 너무 좋아 ... 이제 어떻게해야합니까?

내가 해야 할 것 같아

  • 가장 다른 패턴을 먼저 방해하는 형태부터 시작하여 충돌하는 형태의 다양한 조합을 시도하십시오. 이것에 어떻게 접근합니까?
  • 8 개의 블록을 차지하는 3 개의 상충되는 모양이 있고 각 모양은 4 개의 블록이므로 최대 2 개의 모양 만 가질 수 있다는 합리적인 설명을 사용하십시오.

(나는 또한 다른 모양을 통합하려고하며 충돌하는 모양을 겪을 때 고려해야 할 점수 가중치가있을 것이지만 다른 날이 될 수 있습니다)

빈 포장 문제라고 생각하지 않지만 무엇을 찾아야할지 모르겠습니다. 이해가 되길 바랍니다. 도움을 주셔서 감사합니다.

편집 질문의 명확성에도 불구하고 모두가 이해 한 것 같습니다.

각 색상 내에서 최대 "T"모양을 찾고 싶습니다

(내가 당신에게 2 점을 주었고 당신이 3 점을 만들었다면, 당신은 약간 짜증날 것입니다)


탐욕스러운 알고리즘은 보드를 결합 된 블록 모음으로 분할하는 것입니다. 그런 다음 각 컬렉션에 대해 모양으로 채우기를 시도하고 어둡지 않은 블록의 양에 따라 채우기에 점수를 줄 수 있습니다. 내가 en.wikipedia.org/wiki/Knapsack_problem을 생각하게 만듭니다 .
— Jonathan Connell

2
질문에 빠진 것이 있다고 생각합니다. "T"모양의 그룹을 가능한 많이 찾는 알고리즘을 만들고 싶습니까?
— Markus von Broady

내가 당신을 이해한다면 당신은 올바른 길을 가고 있습니다. 당신은 매우 명확하지 않으며 당신이 정교하게 할 수 있다면 그것을 좋아할 것입니다.
— AturSams

답변:


3

빨간색으로 표시된 블록이 파란색이고 알고리즘이 T 모양을 발견하고 빨간색으로 표시했는지 확인하겠습니다. 맞습니까? 귀하의 목표는 동일한 색상 블록으로 가능한 많은 T 모양을 찾는 것입니다. 현재는 일단 찾은 후에 표시하면 알고리즘의 유용성이 떨어집니다 (최적의 솔루션을 놓칠 수 있으므로). 모든 모양을 검색 한 다음 사용할 모양과 사용하지 않을 모양을 선택하려고합니다. 지금까지 내가 맞습니까? 알고리즘이 완료 될 때 T 모양 안에 포함 된 블록의 양을 최대화하려고합니다.

내가 맞다면 다음은 귀하의 상황에 맞는 최적의 솔루션입니다.

우리는 Integer Linear Programming을 사용할 것입니다.

나는 이것을 과거에 사용했다고 생각합니다.

http://sourceforge.net/projects/lpsolve/

http://lpsolve.sourceforge.net/5.5/Java/README.html

(여러 언어로 작동하도록 할 수 있습니다 .PHP, Java 및 C와 함께 사용했습니다)

우리가 할 일은 보드에 가능한 모든 T 모양을 등록한 다음 ILP를 사용하여 덮는 블록의 양을 최대화하는 것입니다. ILP는 기하 급수적으로 복잡합니다. 보드의 크기를 고려하면 문제가되지 않습니다. ILP가있는 그래프에서 훨씬 더 복잡한 최소 / 최대 질문을 실행했으며 수백 개의 정점으로 30 분에서 90 초까지 완료되었습니다 (귀하의 경우 1 초에 해당).

내가 추천하는 것 :

  1. 가능한 모든 선 모양 찾기
  2. 같은 색상의 선 모양 사이의 모든 교차점 찾기
  3. 모든 교차점을 검색하여 가능한 모든 T 모양을 찾으십시오.
  4. 각 T 모양에 대한 선형 문제에서 부울 변수 정의 ( 0 <= Bi <= 1) 값은 정수이므로 0 또는 1로 남습니다.
  5. 교차하는 T 모양의 각 쌍에 대한 조건을 만듭니다 ( Bi + Bj <= 1).
  6. 목적 함수는 다음과 같습니다 ( "T"모양의 블록 합계 (i) * Bi)
  7. 솔버를 실행하고 최적의 솔루션에서 솔버의 해당 부울이 1 인 T 모양을 어둡게합니다.

이것은 귀중한 지식입니다. 작업 프로젝트에 선형 솔버를 자주 사용했습니다.

ILP는 기본적으로 일부 선형 함수에 대해 최대 또는 최소를 달성하려는 선택 문제를 해결하는 방법입니다.

Integer를 사용하여 더 많은 것을 읽을 수 있습니다. 선형 프로그래밍 및 선형 프로그래밍은 프로그래머에게 동일하며 Integer는 컴퓨터에서 훨씬 더 복잡하여 실행 시간이 길어질 수 있습니다. 귀하의 경우가 아니라면 매우 간단하며 최악의 경우 밀리 초 미만이어야합니다.

나는 당신이 여기에서 더 많은 것을 읽을 수 있다고 생각합니다 :

http://en.wikipedia.org/wiki/Integer_linear_programming#Integer_unknowns

이것은 그것을 잘 설명합니다 :

http://fisher.osu.edu/~croxton_4/tutorial/

기본적으로 의사 결정 문제 해결사이며 원하는 결과를 최대화하는 의사 결정 방법입니다. 이것은 결과를 판단하는 기능이 특정 현재의 경우 선형이라고 가정합니다. 이 경우 결과를 판단하는 기능은 어둡게하기로 결정한 모든 T 모양의 블록을 요약합니다.

수학적으로 변수를 설정하는 방법 : 현재의 경우 부울 (인덱스 i로 T 모양을 어둡게 했습니까?)을 최적의 값으로 설정하여 원하는 결과를 최대화합니다. 교차하는 T 모양을 어둡게하지 않고 가능한 한 많은 블록을 어둡게합니다. 모든 변수를 설정했을 때 원하는 결과를 선형 함수로 계산할 수 있으면 해결됩니다. 이 경우 어둡게 한 T 모양을 확인하고 해당 블록을 합산합니다.

여기에 이미지 설명을 입력하십시오

나는 이것이 사소한 것이 아니라는 것을 알고 있습니다.


도와 주셔서 감사합니다. 다이제스트하는 데 몇 번의 읽기가 필요할 수 있습니다. 그리고 네, 당신은 문제를 올바르게 이해했습니다. 나는 당신이 정교해야한다면 매우 관심이있을 것입니다 (아니, 사소한 것이 아닙니다).
— 어셈블러

구현에 어떤 언어를 사용하고 있습니까?
— AturSams

액션 스크립트 3! 모두가 좋아하는!
— 어셈블러

여기에서도 마찬가지입니다. 나는 as3로 구현을 작성하고 단계별로 작업하면서 주석이 달린 다운로드를 위해 github에 업로드 할 것입니다
— AturSams

의견을 추가하거나 정교하게 설명 할 특정 영역이 1 ~ 7 있습니까? btw, AS3 애호가들에게 희소식, Adobe는 C ++를 지원하는 FlasCC를 출시하여 기존 선형 솔버를 쉽게 사용할 수 있습니다. :)
— AturSams

4

그리드에서 발생하는 모든 (겹칠 수있는) T 자형 목록이 있으면 남은 것은 최대 세트 패킹 문제입니다.

일반적으로 이것은 NP- 완전 문제입니다. 그러나 그리드는 크기가 작아서 (일반적으로 더 작은 독립적 인 하위 문제로 분류 됨) 정확한 솔루션을 얻는 것이 가능할 수 있습니다.


부록 : 다음은 트릭을 수행 할 수있는 기본 역 추적 검색 알고리즘입니다.

function max_packing_recursive ( set A, set S, set M ):
    if |M| < |S| then let M = S;
    for each shape X in A do:
        remove X from A;
        let B = A;
        remove all shapes that intersect with X from B;
        if |M| < |B| + |S| + 1 then:        // upper bound
            let M = max_packing_recursive( B, S + {X}, M );
        end if
        if |M| >= |A| + |S| then return M;  // shortcut
    end for
    return M;
end function

function max_packing( set A ):
    return max_packing_recursive( A, {}, {} );
end function

여기서, {X, Y, Z}요소를 포함하는 세트이고 X, Y및 Z(와 {}공집합 인), 및 |Q|세트의 크기를 나타낸다 Q.

재귀 함수에서 집합 A은 나머지 솔루션에 사용 가능한 S모양을 포함하고 현재 솔루션 후보의 모양을 포함하며 M지금까지 최대 솔루션입니다 (이를 다시 반환하는 대신 전역 변수로 저장하려고 할 수 있음) 콜 체인). 중요한 최적화는로 표시된 줄에 있으며 // upper bound,이 방법은보다 나은 솔루션을 반환 할 수없는 검색 트리 분기를 제거합니다 M.

(사실, 우리는 각각의 T 자형 정확히 네 개의 사이트를 포함 것을 알고 있기 때문에 더 나은 상단 대체함으로써 얻을 수 바인딩 |B|의 모양에 포함 별개의 사이트 수에 B대한 유사 네 가지로 나누어, 그리고 내림 (그리고 |A|온 라인으로 표시 // shortcut). 상기 알고리즘을 지정하지만, 임의의 형상의 컬렉션에 대해 작동한다.)

위에서 구현하지 않은 가능한 추가 최적화는 재귀 함수의 시작 부분 A에서 서로 다른 하위 집합의 모양이 겹치지 않는다는 의미에서 독립적 인 여러 하위 집합으로 나뉘 는지 여부를 확인 하는 것입니다. 알고리즘을 각 하위 집합에 개별적으로 할당합니다. (어쨌든 재귀 알고리즘을 호출 하기 전에 최상위 수준에서이 작업을 적어도 한 번 이상 수행하고 싶을 것 입니다.) A반복되는 모양의 수에 따라 순서를 반복하여 반복하기 전에 모양을 적절히 정렬하면 도움이 될 수 있습니다. .


그래, 나는 문제의 크기 때문에 ILP를 사용하여 상대적으로 고통없이 해결할 수 있다고 생각합니다. . 그것은 분명히 지수 적으로 복잡합니다 (적어도 누군가 p = np임을 증명할 때까지). 크기는 비교적 간단한 경우 휴리스틱을 피할 수 있습니다.
— AturSams

일 마리, 대단히 감사합니다. 이 답변도 이해하는 데 몇 가지가 필요합니다. 임의의 모양 비트는 향후 반복에 유용 할 수 있습니다.
— 어셈블러
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.