Thuật toán nhánh cậnNhững bài toán áp dụng thuật toán nhánh cận không phải là bài toán khó. Vì đã xây dựng thành thuật toán thì cứ thế mà áp dụng. Những bài toán này, chẳng đòi hỏi Khách viếng thăm là người phải thông minh xuất chúng gì cả, mà là những bài toán yêu cầu sinh viên phải tỉ mỉ, cẩn thận và thực tế rất chua chát là những bài này khi cho vào các bài thi lại là bài giết thí sinh nhiều nhất. Bản thân nó không khó, nhưng vì khi giải nó rất dài dòng và tốn kém (tốn giấy đã đành vì mỗi bài phải viết tới vài trang) nó còn dã man ở chỗ là khiến thí sinh phải dành rất nhiều thời gian làm các phép tính cộng cộng, trừ trừ đơn giản. Các đề thi đưa thuật toán nhánh cận để tuyển thạc sĩ hay tiến sĩ thì có nghĩa là người ra đề cũng muốn biến các "thạc sĩ, tiến sĩ tương lai" thành một chút công nhân lao động khổ sai. Nó âm thầm tiêu diệt nguồn tài sản quý nhất của người đi thi đó là thời gian, cho dù thế nào đi nữa, Khách viếng thăm cố làm bài này cũng được trả công rất bạc bẽo. Nếu đề thi có câu này, thì đó là câu bạc bẽo nhất để Khách viếng thăm luôn hiểu rằng cuộc đời nhiều khi thời gian, công sức của mình bỏ ra nhiều nhưng thu được chẳng được bao nhiêu.
Tôi với Admin đều là người đi thi, chẳng có lời khuyên gì. Nếu chẳng biết làm bài nào thì lấy tạm câu này ra làm để giết thời gian lấy phần chăm chỉ, cẩn thận bù vào sự thiếu thông minh, kém cỏi thôi thì cũng là điều vạn bất đắc dĩ. Lẽ ra câu hỏi dạng này thì chỉ nên để ở phần nghiên cứu thôi, cho vào đề thi thì nhiều khi tiêu tốn hai thứ đã nói ở trên đó là thời gian và công sức của cả người đi thi và người chấm thi. Người ra đề dạng này chắc Khách viếng thăm hiểu được sẽ là người như thế nào rồi đấy.
Tôi copy cái ý đoạn văn trên từ một blogger google trên mạng để làm mào đầu cho câu chuyện của chúng ta về cái thuật toán này. Mỗi người nói một kiểu về nó, nhưng có hỏi 100% thí sinh đi thi thì chẳng ai thích làm câu hỏi dạng này cả, chỉ cần để biết thôi. Mấy năm rồi đề thi vào Học viện KTQS không có, nhưng những năm trước có, những đề luyện tập luôn có. Năm nay câu hỏi dạng này có hay không thật khó trả lời, nhưng có một điều chắc chắn rằng, nếu có cho dù biết cách làm mười mươi, nhưng sẽ có nhiều thí sinh bỏ qua, nếu các câu khác hòm hòm. Chẳng ai đâm đầu vào làm bằng tay cái công việc vô bổ này, vì có thể dùng thuật toán hoặc viết giải thuật chỉ mất vài dòng, nhưng cứ làm ra thì tiêu hao thời gian và tàn lực của chúng ta không hề ít.
Tôi cũng chẳng tài ba gì, thôi thì mình lấy tí cần cù gõ vào đây làm căn cứ cho thiên hạ copy vậy, vì có google chẳng có thằng điên nào gõ một bài nhánh cận trên mạng nên hồn. Và cũng để cho những bạn nào vì một lý do bận việc đi đâu đó không đi học được có chỗ để mà tham khảo.
Trong bài toán người du lịch, khi tiến hành tìm kiếm lời giải chúng ta sẽ phân tập các hành trình ra thành 2 tập con:
- Một tập chứa hành trình một cung (i, j) nào đó.
- Tập kia gồm những hành trình không chứa cung này.
Ta gọi việc làm đó là phân nhánh và mỗi tập con nói trên sẽ được gọi là một nhánh hay một nút của cây tìm kiếm.
[You must be registered and logged in to see this image.]Việc phân nhánh sẽ được thực hiện dựa trên một quy tắc Hơristic nào đó cho phép ta rút ngắn quá trình tìm kiếm phương án tối ưu. Sau khi phân nhánh ta sẽ tính cận dưới của giá trị hàm mục tiêu của mỗi một tập con (trên 2 tập trên).Việc tìm kiếm sẽ được tiếp tục trên tập con có giá trị cận dưới nhỏ hơn.
Thủ tục này sẽ tiếp tục cho đến khi thu được một hành trình đầy đủ tức là một phương án của bài toán người du lịch. Khi đó ta chỉ việc xét những tập con các phương án nào có cận dưới nhỏ hơn giá trị hàm mục tiêu tại phương án đã tìm được.
Quá trình phân nhánh và tính cận dưới trên tập các phương án của bài toán thông thường cho phép rút ngắn một cách đáng kể quá trình tìm kiếm do ta loại được khá nhiều tập con chắc chắn không chứa phương án tối ưu.
1. Thủ tục rút gọn (tính chi phí cận dưới)
Rõ ràng tổng chi phí của một hành trình của người du lịch sẽ chứa:
+ đúng một phần tử của mỗi dòng
+ đúng một phần tử của mỗi cột
trong ma trận chi phí C. Do đó, nếu ta trừ đi vào mỗi phần tử của một hàng (một cột) một số α thì chi phí của tất cả hành trình sẽ giảm đi α , vì thế hành trình tối ưu sẽ không thay đổi.
Nên trừ để mỗi dòng, mỗi cột đều chứa ít nhất một số 0 thì tổng các hằng số trừ đó sẽ cho ta cận dưới của mọi hành trình. Thủ tục này gọi là thủ tục rút gọn.
2. Thủ tục cung phân nhánh
Sau khi rút gọn, mỗi hàng, mỗi cột có ít nhất 1 phần tử 0.
Đối với mỗi phần tử 0 này, ta tính chỉ số của nó là tổng các phần tử khác không đang xét và nhỏ nhất tương ứng với hàng và cột đó. Chọn phần tử 0 có chỉ số lớn nhất, tương ứng với cung cần chọn để phân nhánh và đặt phần tử đối xứng với nó qua đường chéo là ∞.
Sau khi đã tiến hành tính cận dưới và phân nhánh, chia các hành trình làm 2 tập con.
- Tập T1 gồm các hành trình chứa cung (p, q)
- Tập T2 gồm các hành trình không chứa cung (p, q)
Đối với tập T1, ma trận chi phí tương ứng C1 nhận được từ ma trận C bằng cách loại bỏ hàng p cột q, kích thước giảm xuống 1 bậc.
Đối với tập T2 ma trận chi phí tương ứng C2 nhận được từ ma trận C bằng cách đặt Cpq = ∞ , tức là trong bước tiếp theo không chọn cung (p, q) nữa.