C ++에서의 역 추적 이해


12

C ++의 기본 사항을 잘 이해하고 재귀가 어떻게 작동하는지 이해합니다. 나는 고전적인 여덟 여왕 문제 와 같은 특정 문제를 발견 하고 역 추적 스도쿠를 해결했습니다.

나는 이것에 관해서는 상당히 길을 잃었다는 것을 알고 있습니다. 재귀 스택으로 돌아가서 문제를 해결하기 위해 다시 시작한다는 개념에 대해 생각을 할 수없는 것 같습니다. 펜과 종이로는 쉬운 것처럼 보이지만 코드를 작성할 때 이러한 문제를 어떻게 시작해야할지 혼란스러워합니다.

백 트래킹 초보자를 대상으로하는 튜토리얼이 있거나이 책이 포함 된 좋은 책이 있다면 도움이 될 것입니다. 누군가이 주제에 대해 밝히거나 괜찮은 참조에 대한 링크를 제공 할 수 있다면 정말 감사 할 것입니다.

그리고 네, 기능적 언어에서는 더 쉬울 것입니다. 그러나 명령형 언어로의 구현도 이해하고 싶습니다.


나는 이것이 좋은 질문이라고 생각하지만, 튜토리얼이나 다른 자료를 요구하는 것보다 역 추적을 설명하라는 요청을 강조하는 것이 더 낫다고 생각합니다. 심층적 인 설명 종류의 답변은 매일 참조 목록보다 뛰어납니다.
Adam Lear

누군가가 자세한 설명을 줄 수 있다면 완벽하지만 참고 문헌을 읽는 것은 중요하지 않습니다. 어디서부터 시작 해야할지 모르겠습니다.
nikhil

답변:


9

... 문제를 해결하기 위해 재귀 스택으로 돌아가서 다시 시작 한다는 개념에 대해 생각할 수없는 것 같습니다 .

역 추적에서 다시 시작하지 않습니다. 대신 현재 상황에서 모든 옵션을 반복합니다.

미로에 대한 해결책을 찾는 것에 대해 생각하십시오. 두 개의 다른 경로가있는 지점에서 왼쪽을 먼저 시도하십시오. 왼쪽이 출구로 연결되지 않으면 해당 지점으로 돌아가서 다른 경로를 시도하십시오. 이것이 역 추적의 작동 방식입니다. 역 추적을 사용할 수있는 8 Q 및 기타 문제에서 혼란스러운 부분은 문제 영역에 있습니다. 결정적 방식으로 주어진 상황에서 옵션을 반복하는 방법입니다.

편집 : 다음은 역 추적 이해를 돕는 의사 코드입니다.

# depending on the problem, backtracking is not necessarily calling the
# method itself directly. for now, let's just stick with the simple case.

def backtracking(state)
  option_list = state.get_all_options
  option_list.each {|option|
    state.apply option
    return resolved if state.is_resolved
    return resolved if backtracking(state) == resolved
    state.undo option
  }
  return not_resolved
end

8Q 질문 :

  • state.get_all_options는 다음 여왕의 가능한 위치 목록을 반환합니다
  • state.is_resolved는 모든 여왕이 보드에 있는지 그리고 서로 잘 지내는지를 테스트합니다.
  • state.apply 및 state.undo는 위치를 적용하거나 취소하기 위해 보드를 수정합니다.

할당을 위해 (1984 년 Pascal을 사용하여) 작성한 최초의 재귀 코드는 미로 해결 알고리즘이었습니다.
Gerry

실제로이 물건의 실제 느낌을 얻기 위해 코드를 작성할 수있는 간단한 할당을 알고 있습니다.
nikhil

@ nikhil : 간단한 문제가 있는지 묻고 있습니까? 역 추적의 일반적인 라우팅을 보여주기 위해 의사 코드를 작성하는 것이 좋습니다. 나중에 답장으로 시도하겠습니다.
Codism

그렇습니다. 가장 도움이 될 것입니다.
nikhil 2016 년

정말 고마워요, 최근 몇 가지 내용을 읽었습니다. 천천히 그러나 꾸준히 나의 이해가 향상되고 있습니다.
nikhil

5

이진 트리를 걷는 프로그램을 보았습니다. 다음과 같이 보입니다 :

void walk(node* p){
  if (p == NULL) return;  // this is backtracking
  else if (WeWin(p)){
    // print We Win !!
    // do a Throw, or otherwise quit
  }
  else {
    walk(p->left);   // first try moving to the left
    walk(p->right);  // if we didn't win, try moving to the right
                     // if we still didn't win, just return (i.e. backtrack)
  }
}

역 추적이 있습니다.

실제로 물리적 트리가 필요하지 않습니다. 당신이 필요로하는 것은 움직일 수 있고 나중에 취소하거나, 이겼는지, 더 이상 갈 수 없는지 알려주는 방법입니다.


1
하위 트리에서 솔루션이 있는지 확인하기 위해 bool / int를 반환 할 수 없습니까? 예상 결과 else{return walk(p->left)||walk(p->right));}를 던질 필요가 없습니다
ratchet freak

@ratchet : 물론입니다. 그것은 또한 그것을하는 완벽한 방법입니다. (나는 단지 예제를 혼란스럽게 만들려고 노력했다. 나는 실제로 당신의 방식으로 그것을 할 것이다.)
Mike Dunlavey

@MikeDunlavey 절단은 실제로 중요한 종류입니다.
jupp0r
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.