Hiểu về quay lui trong C ++


12

Tôi có một sự hiểu biết cơ bản tốt về các nguyên tắc cơ bản của C ++, tôi cũng có một sự hiểu biết về cách thức đệ quy hoạt động. Tôi đã gặp một số vấn đề nhất định như vấn đề tám nữ hoàng cổ điển và giải Sudoku bằng Backtracking.

Tôi nhận ra rằng tôi khá lạc lõng khi nói về điều này, dường như tôi không thể có được suy nghĩ về khái niệm quay trở lại trong ngăn xếp đệ quy và bắt đầu lại để giải quyết vấn đề. Nó có vẻ dễ dàng với một cây bút và giấy nhưng khi viết mã cho việc này, tôi bối rối về cách bắt đầu tấn công những vấn đề này.

Sẽ rất hữu ích nếu có một hướng dẫn dành cho người mới bắt đầu quay lại hoặc nếu có một cuốn sách hay trong đó cuốn sách này được đề cập. Nếu ai đó có thể làm sáng tỏ chủ đề này hoặc cho tôi một số liên kết đến các tài liệu tham khảo phong nha, tôi thực sự rất biết ơn.

Và vâng tôi biết rằng nó sẽ dễ dàng hơn trong các ngôn ngữ chức năng nhưng tôi cũng muốn hiểu việc thực hiện bằng các ngôn ngữ bắt buộc.


Tôi nghĩ rằng đây là một câu hỏi hay, nhưng tôi nghĩ sẽ tốt hơn nếu nhấn mạnh yêu cầu ai đó giải thích việc quay lại bằng cách yêu cầu hướng dẫn hoặc các tài nguyên khác. Một loại câu trả lời chuyên sâu đánh bại một danh sách các tài liệu tham khảo bất cứ ngày nào.
Adam Lear

Sẽ thật hoàn hảo nếu ai đó có thể đưa ra lời giải thích chi tiết, nhưng tôi cũng không ngại đọc các tài liệu tham khảo. Chỉ là tôi không biết bắt đầu từ đâu.
nikhil

Câu trả lời:


9

... Tôi dường như không thể có được suy nghĩ về khái niệm quay trở lại trong ngăn đệ quy và bắt đầu lại để giải quyết vấn đề.

Trong quay lại, bạn không bắt đầu lại. Thay vào đó, bạn lặp qua tất cả các tùy chọn ở tình huống hiện tại.

Hãy suy nghĩ về việc tìm giải pháp cho một mê cung. Tại một thời điểm mà bạn có hai con đường khác nhau, bạn thử bên trái trước. Nếu bên trái không dẫn bạn đến lối ra, bạn quay lại điểm và thử đường dẫn khác. Đó là cách quay lui hoạt động. Trong 8 Q và các vấn đề khác có thể sử dụng quay lui, phần khó hiểu nằm trong miền vấn đề - cách lặp qua các tùy chọn của bạn trong một tình huống nhất định theo cách xác định.

EDIT : sau đây là một mã giả giúp hiểu về quay lui.

# 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

Đối với câu hỏi 8Q:

  • state.get_all_options sẽ trả về danh sách các vị trí có thể cho nữ hoàng tiếp theo
  • state.is_resolve sẽ kiểm tra xem tất cả các nữ hoàng có ở trên bảng không và liệu họ có tốt với nhau không.
  • state.apply và state.undo sẽ sửa đổi bảng để áp dụng hoặc hoàn tác định vị.

Mã đệ quy đầu tiên tôi đã viết (năm 1984 sử dụng Pascal) cho một bài tập là một thuật toán giải mê cung.
Gerry

Biết một số bài tập đơn giản mà tôi thực sự có thể viết mã để có được cảm giác thực sự của công cụ này.
nikhil

@nikhil: bạn đang hỏi nếu có một số vấn đề đơn giản? Tốt hơn là viết một số mã giả để chứng minh định tuyến chung của quay lui. Tôi sẽ thử một lần sau trong một trả lời.
Codism

Vâng chính xác, điều đó sẽ hữu ích nhất.
nikhil

Cảm ơn bạn rất nhiều, tôi đã đọc một số thứ gần đây. Dần dần nhưng dần dần sự hiểu biết của tôi được cải thiện.
nikhil

5

Bạn đã thấy một chương trình đi bộ cây nhị phân, phải không? Nó trông như thế này:

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

Có quay lại của bạn.

Bạn không thực sự cần một cây vật lý. Tất cả những gì bạn cần là một cách để di chuyển và sau đó hoàn tác nó, hoặc nói nếu bạn đã thắng, hoặc nói nếu bạn không thể tiến xa hơn.


1
bạn không thể trả lại bool / int để kiểm tra xem giải pháp có được tìm thấy trong cây con không? else{return walk(p->left)||walk(p->right));}không cần ném cho kết quả mong đợi
ratchet freak

@ratchet: Hoàn toàn đúng. Đó cũng là một cách hoàn toàn tốt để làm điều đó. (Tôi chỉ cố gắng làm xáo trộn ví dụ. Tôi thực sự sẽ làm theo cách của bạn.)
Mike Dunlavey

@MikeDunlavey cắt là loại quan trọng trong thực tế, mặc dù.
jupp0r
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.