Google 코드 잼 만리 장성 문제에 대한 더 빠른 솔루션이 있습니까?


16

다음 Google 코드 잼 1C 질문을 고려하십시오 .

만리 장성은 무한 선으로 시작하여 모든 위치의 높이가 입니다.0

일부 부족 , N 1000 은 시작일, D , 시작 강도 S , 시작 서쪽 좌표 W 및 시작 동쪽 좌표 E 에 따라 다음과 같은 매개 변수에 따라 벽을 공격합니다 . 이 첫 번째 공격은 D 일, 범위 [ W , E ] 에서 강도 S에서 발생 합니다. [ W , E ] 내에 높이 < S 인 만리장성의 부분이있는 경우NN1000DSWED[W,E]S[W,E]<S, 공격이 성공하고 하루가 끝날 때, 높이 < S 내에있는 벽의 세그먼트가 높이 S (또는 다른 공격 인 경우)보다 커지 도록 벽이 쌓입니다. 그날은 힘 S ' > S 와 같은 세그먼트에 부딪쳤다 )[W,E]<SSS>S

각 부족은 퇴각하기 전에 최대 공격 을 수행 하며 각 공격은 이전 공격에서 반복적으로 결정됩니다. 모든 부족은 일부가 δ의 D , δ Xδ S 공격을 자신의 순서를 결정하십시오 기다립니다 δ D1 , 그들의 공격 범위 이동 공격 사이의 일 δ X 각 공격 유닛 (음 = 서쪽, 긍정적 =을 범위)의 크기는 동일하게 유지되지만 각 공격 후에는 강도가 일정한 값만큼 증가 / 감소합니다.1000δDδXδSδD1δX

문제의 목표는 공격 부족에 대한 완전한 설명이 주어지면 공격의 성공 횟수를 결정하는 것입니다.

나는 약 20 초 안에 작동하는 솔루션을 코딩 할 수있었습니다. 구현 한 솔루션에 시간이 걸립니다 .A = 시뮬레이션의 총 공격 수 (max 1000000 ), X = 공격 범위의 총 고유 에지 포인트 수 (max 2000000 ).O(AlogA+(A+X)logX)A=1000000X=2000000

높은 수준에서 내 솔루션 :

  • 모든 부족 정보를 읽습니다.
  • 공격 범위에 대한 모든 고유 한 좌표를 계산합니다 -O ( A )XO(A)
  • XXO(XlogX)
  • 모든 부족이 수행 할 모든 공격을 생성하고 별로 정렬합니다.O(AlogA)
  • logXlogXO(AlogX)

O(AlogA+(A+X)logX)


3
닫지 마십시오. 유효한 질문입니다. 대답은 우리가 할 수있는 최선의 방법이라면 더 잘 할 수 없다는 것을 보여주는 하한 증거입니다. 예를 들어, 여기에서 요소 구별 문제를 사용할 수있을 것으로 생각하지만 생각할 시간을 찾지 못했습니다.
Aryabhata

다음에 계속 열어 보겠습니다 :)
torquestomp 16:16에

답변:


2

개선의 여지가 분명한 것은이 단계입니다.

모든 부족이 수행 할 모든 공격을 생성하고 별로 정렬합니다.O(AlogA)

우리는 부족들이 특정한 날부터 정기적으로 공격 할 것임을 알고 있습니다. 그것은 우리가 본질적으로 많은 미리 분류 된리스트를 병합해야한다는 것을 의미합니다. 또한 문제 성명서에는 1,000 명 이상의 부족 (즉 1,000 명을 합병 할 수있는 사람)이 없을 것입니다. 1,000,000 최대 공격에 비해 작은 숫자! 구현의 상대 타이밍에 따라이를 전환하면 처리 시간이 절반으로 단축 될 수 있습니다.

이것이 이론적 인 복잡성을 최적화하기 위해 제안 할 수있는 모든 것이지만,이 변경 이후에 그것이 최적이라는 증거는 없습니다.


퍼즐을 직접 만들었지 만 std::map벽의 높이가 변하는 위치를 저장 하는 이진 검색 트리 ( 정확히 말하면 C ++ )를 사용했습니다. 이를 통해 필자는 필요에 따라 노드를 추가 및 제거 할 수있었습니다 (예 : 복잡한 섹션이 대규모의 압도적 인 공격 또는 동일한 강도의 여러 공격에 노출 된 경우 노드 수는 크게 줄어 듭니다). 이것은 3.9 초 만에 큰 입력을 해결했습니다 (중간 사양 개발 랩톱에서). 개선해야 할 몇 가지 이유가 있다고 생각합니다.

  • 지적했듯이 boxing과 unboxing은 비쌀 수 있지만 C ++의 템플릿 기반 컨테이너는 이것을 완전히 피합니다.
  • 필자가 사용한 벽 표현은 이론적으로 더 나쁘지만 대부분의 경우 노드 수를 동적으로 줄여 초고속으로 만들었습니다 (대부분의 테스트 사례는 1k 노드 미만에서 최대치였으며 2를 제외한 모든 모델은 10k 미만 임) . 실제로, 상당한 시간이 걸린 유일한 사례는 # 7인데, 교차하지 않는 많은 범위를 테스트 한 것으로 보입니다.
  • 전처리를 사용하지 않았습니다 (단계는 각 부족이 다음에 언제 공격을하는지 추적하고 각 턴마다 가장 낮은 조인트를 검색하여 결정됩니다). 다시 말하지만 이것은 이론적으로 더 나쁘지만 대부분의 경우 오버 헤드가 낮을수록 더 빠르다고 생각합니다 (테스트하고 다시 연락 드리겠습니다). 업데이트 : 위에서 설명한 방법과 비슷한 공격에 우선 순위 대기열을 추가했습니다 (큰 배열을 만드는 대신 즉시 계산했습니다). 큰 입력의 경우 시간이 3.0 초로 감소했습니다.

요컨대, 일반적인 경우 알고리즘이 거의 최적이라고 생각하지만 일반적인 입력 속도를 높이는 방법에는 여러 가지가 있습니다 .


1

다음은 답변이므로 질문에서 제거되었습니다.

다른 토론과 성공적인 솔루션을 살펴본 결과 내가 설명한 솔루션이 예상되는 알고리즘이라는 것을 알 수 있습니다. 내 솔루션의 속도 저하는 아마도 배열 기반이 아닌 자동 복싱 및 포인터 기반 트리 구조의 지연 사용 때문일 수 있습니다. 따라서 솔루션이 존재하면 아마도 전체가 아니라고 생각합니다. 여기있는 것보다 훨씬 낫습니다.

해결책은 여기 에서 찾을 수 있습니다 . 여기에 게시 한 내용과 매우 동일합니다. 따라서 더 효율적인 솔루션이 존재하지 않는다고 생각하는 경향이 훨씬 큽니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.