C ++ 'da Geri İzlemeyi Anlama


12

C ++ 'ın temelleri hakkında iyi bir temel anlayışa sahibim, ayrıca özyinelemenin nasıl çalıştığını da anlıyorum. Klasik sekiz kraliçe problemi ve Sudoku'yu Backtracking ile çözme gibi bazı sorunlarla karşılaştım .

Bu konuda oldukça kayıp olduğumu fark ettim, sorunu çözmek için özyineleme yığınına geri dönme ve tekrar başlama kavramı etrafında aklımdan çıkamıyorum. Bir kalem ve kağıtla kolay görünüyor, ancak bunun için kod yazmaya gelince, bu sorunlara saldırmaya nasıl başlayacağım konusunda kafam karıştı.

Yeni başlayanların geri izlemeye yönelik bir öğretici olması veya bunun ele alındığı iyi bir kitap olması yararlı olacaktır. Birisi bu konuya ışık tutabilir veya bana iyi referanslara bazı bağlantılar verebilirse, gerçekten minnettar olurum.

Ve evet, işlevsel dillerde daha kolay olacağını biliyorum ama uygulamayı zorunlu dillerde de anlamak istiyorum.


Bunun iyi bir soru olduğunu düşünüyorum, ancak birisinin öğreticiler veya diğer kaynaklar sorma konusunda geri izlemeyi açıklama isteğini vurgulamanın daha iyi olacağını düşünüyorum. Ayrıntılı bir açıklama türü, her gün bir referans listesini yener.
Adam Lear

Birisi ayrıntılı bir açıklama verebilirse mükemmel olurdu, ama referansları da okumayı umursamıyorum. Sadece nereden başlayacağımı bilmiyorum.
nikhil

Yanıtlar:


9

... sorunu çözmek için özyineleme yığınına geri dönme ve yeniden başlama kavramını aklımdan çıkaramıyorum .

Geri izlemede, yeniden başlamıyorsunuz. Bunun yerine, mevcut durumdaki tüm seçenekler arasında yineleme yaparsınız.

Bir labirent için çözüm bulmayı düşünün. İki farklı yolunuzun olduğu bir noktada, önce sol olanı deneyin. Sol taraf sizi çıkışa götürmezse, noktaya dönüp diğer yolu denersiniz. Geri izleme böyle çalışır. 8 Q'da ve geri izlemenin kullanılabileceği diğer problemlerde, kafa karıştırıcı kısım problem alanındadır - belirli bir durumda seçenekleriniz arasında belirleyici bir şekilde nasıl yinelenir.

DÜZENLEME : Aşağıda, geri izlemeyi anlamaya yardımcı olan bir sahte kod verilmiştir.

# 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 sorusu için:

  • state.get_all_options sonraki kraliçe için olası pozisyonların bir listesini döndürür
  • state.is_resolved, tüm kraliçelerin tahtada olup olmadığını ve birbirleriyle iyi olup olmadığını test eder.
  • state.apply ve state.undo bir konumlandırma uygulamak veya geri almak için kartı değiştirir.

Bir ödev için yazdığım ilk özyinelemeli kod (1984'te Pascal kullanarak) bir labirent çözme algoritmasıydı.
Gerry

Aslında bu şeylerin gerçek hissediyorum almak için kod yazabilirsiniz bazı basit atama biliyorum.
nikhil

@nikhil: Basit bir sorun olup olmadığını mı soruyorsunuz? Geri izlemenin genel yönlendirmesini göstermek için bazı sahte kodlar yazmak daha iyidir. Bir cevapta daha sonra deneyeceğim.
Codism

Evet kesinlikle, bu çok yardımcı olacak.
nikhil

Çok teşekkür ederim, son zamanlarda bazı şeyler okuyorum. Yavaş ama istikrarlı bir şekilde anlayışım gelişiyor.
nikhil

5

İkili ağaçta yürümek için bir program gördün değil mi? Şöyle görünüyor:

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)
  }
}

İşte geri izlemeniz.

Aslında fiziksel bir ağaca ihtiyacınız yok. İhtiyacınız olan tek şey, bir hamle yapmanın ve daha sonra geri almanın veya kazanıp kazanmadığınızı veya daha fazla ilerleyemeyeceğinizi söylemenin bir yoludur.


1
çözümün alt ağaçta bulunup bulunmadığını kontrol etmek için bir bool / int döndüremez misiniz? beklenen sonuç else{return walk(p->left)||walk(p->right));}için atmaya gerek yok
cırcır ucube

@ratchet: Kesinlikle. Bu da bunu yapmanın mükemmel bir yoludur. (Sadece örneği
dağıtmaya

@MikeDunlavey kesim pratikte biraz önemlidir.
jupp0r
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.