Một cách trực tiếp là một thủ tục đệ quy thực hiện như sau trên mỗi lần gọi. Đầu vào của thủ tục là một danh sách các cặp đã được chọn và một danh sách tất cả các cặp.
- Tính số nhỏ nhất chưa có trong danh sách đầu vào. Đối với lần gọi đầu tiên, tất nhiên đây sẽ là 0, vì không có cặp nào được chọn.
- Nếu tất cả các số được bảo hiểm, bạn có một kết hợp chính xác, in nó ra và trả lại bước trước đó. Mặt khác, con số nhỏ nhất chưa được khám phá là mục tiêu chúng ta sẽ nhắm tới.
- Tìm kiếm thông qua các cặp tìm kiếm một cách để bao gồm số mục tiêu. Nếu không có, thì chỉ cần quay lại mức đệ quy trước đó.
- Nếu có một cách để bao gồm số mục tiêu, hãy chọn cách đầu tiên và gọi lại toàn bộ quy trình một lần nữa, với cặp chỉ cần chọn thêm vào danh sách các cặp đã chọn.
- Khi trả về, hãy tìm cách tiếp theo để che số mục tiêu bằng một cặp, mà không chồng chéo một cặp đã chọn trước đó. Nếu bạn tìm thấy một, chọn nó và một lần nữa gọi đệ quy tiếp theo.
- Tiếp tục bước 4 và 5 cho đến khi không còn cách nào khác để che số mục tiêu. Đi qua toàn bộ danh sách các cặp. Khi không có lựa chọn chính xác hơn, quay trở lại mức đệ quy trước đó.
Cách để hình dung thuật toán này là với một cây có các đường dẫn là chuỗi các cặp không chồng chéo. Cấp độ đầu tiên của cây chứa tất cả các cặp chứa 0. Đối với ví dụ trên, cây là
Nguồn gốc
|
----------------
| | |
(0,1) (0,2) (0,3)
| | |
(2,3) (1,3) (1,2)
Trong ví dụ này, tất cả các đường dẫn qua cây thực sự cho các bộ sưu tập chính xác, nhưng ví dụ nếu chúng ta bỏ qua cặp (1,2) thì đường dẫn ngoài cùng bên phải sẽ chỉ có một nút và sẽ tương ứng với tìm kiếm ở bước 3 không thành công.
Các thuật toán tìm kiếm thuộc loại này có thể được phát triển cho nhiều vấn đề tương tự như liệt kê tất cả các đối tượng của một loại cụ thể.
Có ý kiến cho rằng có lẽ OP có nghĩa là tất cả các cặp đều ở đầu vào, không chỉ là một bộ trong số chúng như câu hỏi nói. Trong trường hợp đó, thuật toán dễ dàng hơn nhiều vì không còn cần thiết phải kiểm tra cặp nào được phép. Thậm chí không cần thiết phải tạo tập hợp tất cả các cặp; mã giả sau đây sẽ làm những gì OP yêu cầu. Ở đây là số đầu vào, "danh sách" bắt đầu là một danh sách trống và "được bảo hiểm" là một mảng có độ dài n được khởi tạo thành 0. Nó có thể được thực hiện hiệu quả hơn một chút nhưng đó không phải là mục tiêu trước mắt của tôi.nn
sub cover {
i = 0;
while ( (i < n) && (covered[i] == 1 )) {
i++;
}
if ( i == n ) { print list; return;}
covered[i] = 1;
for ( j = 0; j < n; j++ ) {
if ( covered[j] == 0 ) {
covered[j] = 1;
push list, [i,j];
cover();
pop list;
covered[j] = 0;
}
}
covered[i] = 0;
}