Lập trình động khác với lực lượng Brute như thế nào


19

Tôi đang đọc về Lập trình động khi tôi thấy đoạn trích dẫn sau

Một thuật toán lập trình động sẽ kiểm tra tất cả các cách có thể để giải quyết vấn đề và sẽ chọn giải pháp tốt nhất. Do đó, chúng ta có thể nghĩ đại khái về lập trình động như một phương pháp thông minh, mạnh mẽ cho phép chúng ta đi qua tất cả các giải pháp có thể để chọn ra phương pháp tốt nhất . Nếu phạm vi của vấn đề là đi qua tất cả các giải pháp khả thi là có thể và đủ nhanh, lập trình động đảm bảo tìm ra giải pháp tối ưu

Ví dụ sau đây đã được đưa ra

Ví dụ: giả sử bạn phải đi từ điểm A đến điểm B càng nhanh càng tốt, trong một thành phố nhất định, trong giờ cao điểm. Một thuật toán lập trình động sẽ xem xét toàn bộ báo cáo giao thông, xem xét tất cả các kết hợp đường có thể bạn có thể đi và chỉ sau đó sẽ cho bạn biết đường nào là nhanh nhất. Tất nhiên, bạn có thể phải đợi một lúc cho đến khi thuật toán kết thúc và chỉ sau đó bạn mới có thể bắt đầu lái xe. Con đường bạn sẽ đi sẽ là con đường nhanh nhất (giả sử rằng không có gì thay đổi trong môi trường bên ngoài)

Brute Force đang thử mọi giải pháp có thể trước khi quyết định giải pháp tốt nhất.

Lập trình động khác với Brute Force như thế nào nếu nó cũng trải qua tất cả các giải pháp có thể trước khi chọn giải pháp tốt nhất , điểm khác biệt duy nhất tôi thấy là Lập trình động tính đến các yếu tố bổ sung (điều kiện giao thông trong trường hợp này).

Tôi có đúng không khi nói rằng Lập trình động là một tập hợp con của phương thức Brute Force ??


1
Điều kiện giao thông là một cá trích đỏ. Bạn có thể xem xét chúng trong bất kỳ thuật toán.
Yuval Filmus


Trích dẫn đầu tiên của bạn không xác định lập trình động.
rebierpost

@reinierpost Chà, nó cố gắng đến đó intelligent, brute force, nhưng rồi quên mô tả phần "thông minh"
Izkata

@Izkata Theo lý luận đó, mọi thuật toán là "lực lượng vũ phu thông minh" (dù sao cũng là một oxymoron).
Raphael

Câu trả lời:


17

Một thuật toán lập trình động sẽ kiểm tra tất cả các cách có thể để giải quyết vấn đề và sẽ chọn giải pháp tốt nhất.

Tuyên bố này chỉ đơn giản là sai.

Các lần tái lập trình động làm (thường) xem xét tất cả các cách có thể để phân chia trường hợp vấn đề đã cho thành các trường hợp nhỏ hơn theo một sơ đồ nào đó. Tuy nhiên, nó sẽ không kết hợp tất cả các giải pháp cho tất cả các vấn đề một phần với nhau và chọn ra giải pháp tốt nhất - nó chỉ kết hợp các giải pháp một phần tối ưu (và chọn ra giải pháp tốt nhất trong số đó).

Thực tế là điều này mang lại một giải pháp tối ưu cho vấn đề ban đầu không phải là nhỏ và trên thực tế, chỉ giữ cho một số vấn đề. Cụ thể là những người thực hiện nguyên tắc lạc quan của Bellman (một trong những "định nghĩa" tẻ nhạt, bị hiểu lầm nhất thường được trích dẫn). Xem ở đây để biết thêm một số suy nghĩ về điều đó.

Để làm ví dụ cụ thể, hãy xem xét thuật toán Bellman-Ford trên đồ thị hoàn chỉnh với trọng số đơn vị: nó chỉ xem xét các đường dẫn có độ dài một và hai (tức là ) vì những người sử dụng một cạnh đều tối ưu . Nhưng có vô số giải pháp nếu bạn không giới hạn số cạnh tối đa được phép và vẫn cònnhiều nếu bạn cho phép mọi nút chỉ được sử dụng một lần. Rõ ràng, Bellman-Ford - một thuật toán lập trình động - không thực hiện tìm kiếm vũ phu. Θ ( n 2 ) » ( n - 1 ) !KnΘ(n2)(n1)!


"Tuyên bố này hoàn toàn sai" - Khắc phục nó .
nmclean

4
@nmclean Kinh nghiệm của tôi với việc chỉnh sửa các bài viết liên quan đến thuật toán trên Wikipedia đã không còn dễ chịu, nên không. Tôi muốn đầu tư thời gian của tôi ở đây.
Raphael

Tôi đã thử vận ​​may của mình và chỉnh sửa bài báo. Hy vọng nó bây giờ ít sai hơn một chút.
C4stor

9

Lập trình động là thông minh vì nó sử dụng lại tính toán, trong khi lực lượng vũ phu thì không. Giả sử để giải quyết, f (6), bạn cần giải 2 bài toán con mà cả hai đều gọi f (3). Phương pháp brute force sẽ tính toán f (3) hai lần do đó lãng phí công sức trong khi lập trình động sẽ gọi nó một lần, lưu kết quả trong trường hợp tính toán trong tương lai cần sử dụng nó. Trong nhiều vấn đề, động cải thiện độ phức tạp theo cấp số nhân của lực lượng vũ phu thành độ phức tạp đa thức.


9
Đó là ghi nhớ , đó chỉ là một trong nhiều thủ thuật mà DP sử dụng.
Ben Voigt

4
Lực lượng vũ phu với sự phân biệt vẫn không hiệu quả; chỉ có cấu trúc / cắt tỉa bổ sung được cung cấp bởi các đợt tái phát DP làm cho sự phân biệt được đền đáp.
Raphael

3
Tôi không biết gì về lập trình động, nhưng tôi khá chắc chắn rằng có nhiều thứ hơn là chỉ thêm bộ nhớ cache vào thuật toán brute-force. Tôi nghĩ lập trình động tránh việc kiểm tra mọi sự kết hợp có thể bằng cách chia không gian vấn đề, tìm một giải pháp tối ưu cho từng phân khu nhỏ, sau đó kết hợp chúng để tạo ra một giải pháp tổng thể tốt nhất. (Nó có thể thực hiện việc này một cách đệ quy, lặn phụ các bộ phận phụ.) Điều này chỉ hoạt động nếu bạn có thể diễn đạt vấn đề theo cách cho phép kết hợp các giải pháp như thế này mà vẫn đạt được tối ưu tổng thể.
Jonathan Hartley

1
Câu trả lời này thực sự khá chính xác. Tôi khuyên bạn nên đọc một cuốn sách giáo khoa như Cormen et al: "Giới thiệu về thuật toán" để tìm hiểu thêm về lập trình động, cuốn sách này có một chương khá hay về nó. Tóm lại, lập trình động hiệu quả sử dụng hai thuộc tính của vấn đề (tối ưu hóa) mà bạn muốn giải quyết: các giải pháp tối ưu có thể được xây dựng từ các giải pháp tối ưu cho các vấn đề nhỏ hơn và thực tế tổng số các vấn đề nhỏ hơn nhỏ. Sau đó, bạn có thể xây dựng tất cả các giải pháp cho vấn đề phụ từ dưới lên, tăng tốc tính toán với chi phí bộ nhớ.
MRA

Hoặc, để đặt nó theo các thuật ngữ thậm chí đơn giản hơn: Nếu bạn biết cách tính hệ số nhị thức bằng tam giác Pascal thì bạn biết tất cả những gì bạn cần biết về lập trình động.
MRA

3

Sự khác biệt mà bài viết Wikipedia có thể đang cố gắng thực hiện là giữa ba loại thuật toán:

  1. Các thuật toán đi qua tất cả các giải pháp có thể, chọn một giải pháp tối ưu.

  2. Các thuật toán đi qua một tập hợp con của tất cả các giải pháp có thể, được chọn sao cho giải pháp tối ưu thuộc về tập hợp con.

  3. Các thuật toán đi qua một tập hợp con của tất cả các giải pháp có thể, mà không đảm bảo rằng giải pháp tối ưu thuộc về tập hợp con.

Hai loại thuật toán đầu tiên tạo ra giải pháp tối ưu, trong khi loại thứ ba nhằm tạo ra một giải pháp "tốt" hơn là một giải pháp tối ưu. Theo tôi, sự khác biệt giữa hai loại đầu tiên không quá rõ ràng.

Hãy để tôi bắt đầu bằng cách đưa ra các ví dụ đơn giản cho cả ba loại thuật toán, trong bối cảnh đường dẫn ngắn nhất (ví dụ bạn đưa ra).

  1. Hãy thử tất cả các con đường có thể. Điều này được gọi là lực lượng vũ phu .

  2. Hãy thử tất cả các đường dẫn có thể, theo dõi các giải pháp tối thiểu cho đến nay. Bất cứ khi nào con đường hiện tại bạn đang xây dựng đắt hơn giải pháp tối thiểu cho đến nay, hãy từ bỏ nó và chọn một con đường khác (chúng tôi tưởng tượng rằng khoảng cách được tính toán trên cơ sở từng phân khúc). Điều này được gọi là cắt tỉa .

  3. Nhìn vào bản đồ, xem xét một vài con đường và chọn con đường tốt nhất trong số chúng. Đây là một thuật toán cho một con người chứ không phải là một máy tính.

Những ví dụ này khá thô và có lẽ không vẽ nên một bức tranh rất chính xác. Cắt tỉa là rất quan trọng trong nhiều tình huống, ví dụ như trong cờ vua máy tính. Nếu bạn tò mò, hãy tìm thuật toán A * , thực sự được sử dụng cho con đường ngắn nhất.

Lập trình động là một kỹ thuật để tăng tốc đáng kể thuật toán vũ phu. Tuy nhiên, nó là hơi sai lệch khi nghĩ về nó theo cách này. Đây là một kỹ thuật thuật toán để giải quyết các vấn đề tối ưu hóa. Bạn có thể thực hiện cắt tỉa trong bối cảnh lập trình động.

ttt+1t


Và sau đó loại bỏ một ứng cử viên khỏi xem xét mà không xử lý đầy đủ. Ví dụ: tìm tập hợp các số không âm với tổng tối thiểu, bạn thực sự không phải tổng hoàn toàn từng bộ, chỉ đi cho đến khi tổng vượt quá mức tốt nhất hiện tại. Đây là một ý tưởng tương tự như cắt tỉa nhưng trực giao. Kết hợp hai ý tưởng mang lại "nhánh và ràng buộc", trong đó một vấn đề giảm độ phức tạp được giải quyết và được sử dụng để biện minh cho việc cắt tỉa.
Ben Voigt

0

Lập trình động nhanh hơn nhiều so với lực lượng vũ phu. Lực lượng vũ phu có thể mất thời gian theo cấp số nhân, trong khi lập trình động thường nhanh hơn nhiều.

Sự tương tự với lực lượng vũ phu là một điều rất lỏng lẻo. Lập trình động không phải là viên đạn bạc kỳ diệu cho phép bạn thực hiện bất kỳ thuật toán vũ phu nào bạn muốn và làm cho nó hiệu quả.


5
Đó là một hậu quả, không phải là một lời giải thích.
Raphael

-2

Điều này là đơn giản. Lập trình động là một "chiến lược tìm kiếm" sử dụng các yếu tố bổ sung để thu hẹp tìm kiếm. Nếu không có giải pháp trong không gian tìm kiếm, lập trình động sẽ (thường) thực hiện tìm kiếm thông qua mọi yếu tố của không gian tìm kiếm. Nhưng điều đó không có nghĩa là nó là một cuộc tìm kiếm vũ phu.


"Nếu không có giải pháp trong không gian tìm kiếm, lập trình động sẽ (thường) thực hiện tìm kiếm thông qua mọi yếu tố của không gian tìm kiếm." - sai rồi, xem câu trả lời của tôi
Raphael

-2

Tuyên bố rằng lập trình động là lực lượng vũ phu thông minh là chính xác, nhưng hơi khó hiểu với cụm từ đó. Quan điểm của lập trình động nói chung là xử lý một vấn đề và chia nó thành những phần nhỏ hơn một cách thông minh. Sau khi thực hiện xong, bạn sẽ sử dụng lực lượng vũ phu để giải quyết từng mảnh nhỏ, và sau đó bạn sẽ lại sử dụng lực lượng vũ phu để kết hợp các mảnh thành một giải pháp cuối cùng. Vì vậy, trong khi bạn chắc chắn có thể nói rằng lập trình động là một loại giải pháp vũ phu, thì mẹo nằm ở cách bạn sử dụng lực lượng vũ phu đó.


1
"Bạn sẽ sử dụng vũ lực để giải quyết từng mảnh nhỏ" - sai. Thông thường bạn sẽ sử dụng cùng một cách tiếp cận đệ quy.
FrankW
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.