Menu
×

Được chứng nhận

Ghi lại kiến ​​thức của bạn

Đăng nhập Đăng ký

Tạo Tài khoản Example.com.vn miễn phí để cải thiện trải nghiệm học tập của bạn

Người tìm đường và việc học của tôi

Theo dõi tiến độ học tập của bạn tại Example.com.vn và thu thập phần thưởng

Nâng cấp

Trở thành người dùng PLUS và mở khóa các tính năng mạnh mẽ (không có quảng cáo, lưu trữ, hỗ trợ, ..)

Bắt đầu từ đâu

Bạn không chắc chắn muốn bắt đầu từ đâu? Đi theo con đường được hướng dẫn của chúng tôi

Trình chỉnh sửa mã (Dùng thử)

Với trình chỉnh sửa mã trực tuyến của chúng tôi, bạn có thể chỉnh sửa mã và xem kết quả trong trình duyệt của mình

Video

Tìm hiểu những điều cơ bản về HTML qua video hướng dẫn thú vị và hấp dẫn

Mẫu

Chúng tôi đã tạo một loạt mẫu trang web đáp ứng mà bạn có thể sử dụng - miễn phí!

Web hosting

Lưu trữ trang web của riêng bạn và chia sẻ nó với mọi người với Example.com.vn Spaces

Tạo một máy chủ

Tạo máy chủ của riêng bạn bằng Python, PHP, React.js, Node.js, Java, C#, v.v.

Làm thế nào để

Bộ sưu tập lớn các đoạn mã cho HTML, CSS và JavaScript

Khung CSS

Xây dựng các trang web nhanh và phản hồi bằng cách sử dụng khung W3.CSS miễn phí của chúng tôi

Thống kê trình duyệt

Đọc xu hướng dài hạn của việc sử dụng trình duyệt

Tốc độ gõ

Kiểm tra tốc độ đánh máy của bạn

Đào tạo AWS

Tìm hiểu dịch vụ web của Amazon

Bộ chọn màu

Sử dụng công cụ chọn màu của chúng tôi để tìm các màu RGB, HEX và HSL khác nhau. Bánh xe màu hình tròn thể hiện sự chuyển màu trong quang phổ

Trò chơi mã

Trò chơi mã hóa W3Schools! Giúp linh miêu thu thập nón thông Logo Lynx

Đặt mục tiêu

Nhận hành trình học tập được cá nhân hóa dựa trên các kỹ năng và mục tiêu hiện tại của bạn

Bản tin

Tham gia bản tin của chúng tôi và có quyền truy cập vào nội dung độc quyền mỗi tháng

Lớp học

Hãy liên hệ để sử dụng Example.com.vn Plus và các chứng chỉ với tư cách là một tổ chức giáo dục

×
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP CÁCH W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS R TYPESCRIPT ANGULAR GIT POSTGRESQL MONGODB ASP AI GO KOTLIN SASS VUE DSA GEN AI SCIPY AWS AN NINH MẠNG DỮ LIỆU KHOA HỌC

Hướng dẫn DSA

DSA TRANG CHỦ DSA Giới thiệu Thuật toán đơn giản DSA

Mảng

Mảng DSA Sắp xếp bong bóng DSA Sắp xếp lựa chọn DSA Sắp xếp chèn DSA Sắp xếp nhanh DSA Sắp xếp đếm DSA Sắp xếp cơ số DSA Sắp xếp hợp nhất DSA Tìm kiếm tuyến tính DSA Tìm kiếm nhị phân DSA

Danh sách liên kết

Danh sách liên kết DSA Danh sách liên kết DSA trong bộ nhớ Danh sách liên kết DSA Các loại Danh sách liên kết Hoạt động

Ngăn xếp & hàng đợi

Ngăn xếp DSA Hàng đợi DSA

Bảng băm

Bảng băm DSA Bộ băm DSA Bản đồ băm DSA

Cây

Cây DSA Cây nhị phân DSA DSA Traversal đặt hàng trước DSA Traversal theo thứ tự DSA Traversal DSA sau thực hiện mảng DSA Cây tìm kiếm nhị phân DSA Cây AVL DSA

Đồ thị

Đồ thị DSA Thực hiện đồ thị Đồ thị DSA Phát hiện chu trình DSA truyền tải

Con đường ngắn nhất

Đường đi ngắn nhất DSA DSA Bellman-Ford của DSA Dijkstra

Cây bao trùm tối thiểu

Cây khung tối thiểu DSA Prim's DSA Kruskal's

Lưu lượng cực đại

DSA Lưu lượng tối đa DSA Ford-Fulkerson DSA Edmonds-Karp

Độ phức tạp thời gian

Giới thiệu Sắp xếp bong bóng Lựa chọn Sắp xếp Chèn Sắp xếp Sắp xếp nhanh Đếm Sắp xếp Cơ số Sắp xếp Hợp nhất Sắp xếp Tìm kiếm tuyến tính Tìm kiếm nhị phân

Tham chiếu DSA

Thuật toán Euclide DSA Mã hóa DSA Huffman DSA Nhân viên bán hàng du lịch DSA 0/1 Ba lô Ghi nhớ DSA Lập bảng DSA Lập trình động DSA Thuật toán tham lam DSA

Ví dụ về DSA

Ví dụ về DSA Bài tập DSA Câu hỏi DSA Chứng chỉ DSA

Lập trình năng động


Lập trình năng động

Lập trình động là một phương pháp thiết kế các thuật toán.

Một thuật toán được thiết kế bằng Lập trình động sẽ chia bài toán thành các bài toán con, tìm giải pháp cho các bài toán con đó và kết hợp chúng lại với nhau để tạo thành một giải pháp hoàn chỉnh cho bài toán mà chúng ta muốn giải.

Để thiết kế một thuật toán cho một bài toán bằng Lập trình động, bài toán ta muốn giải phải có hai thuộc tính sau:

  • Các bài toán con chồng chéo: Có nghĩa là bài toán có thể được chia thành các bài toán con nhỏ hơn, trong đó lời giải cho các bài toán con này chồng chéo lên nhau. Có các bài toán con chồng chéo có nghĩa là lời giải cho một bài toán con là một phần của lời giải cho một bài toán con khác.
  • Cấu trúc con tối ưu: Có nghĩa là giải pháp hoàn chỉnh cho một vấn đề có thể được xây dựng từ giải pháp của các vấn đề con nhỏ hơn của nó. Vì vậy, bài toán không chỉ phải có các bài toán con chồng chéo mà cấu trúc con còn phải tối ưu để có thể ghép các lời giải của các bài toán con lại với nhau để tạo thành lời giải hoàn chỉnh.

Chúng ta đã thấy Lập trình động trong hướng dẫn này, trong các kỹ thuật ghi nhớlập bảng cũng như để giải các bài toán như Bài toán chiếc ba lô 0/1 hoặc để tìm đường đi ngắn nhất bằng thuật toán Bellman-Ford .

Lưu ý: Một cách khác để thiết kế thuật toán là sử dụng phương pháp tham lam .


Sử dụng lập trình động để tìm số Fibonacci thứ \(n\)

Giả sử chúng ta muốn một thuật toán tìm số Fibonacci thứ \(n\). Chúng tôi chưa biết cách tìm số Fibonacci thứ \(n\), ngoại trừ việc chúng tôi muốn sử dụng Lập trình động để thiết kế thuật toán.

Các số Fibonacci là một dãy số bắt đầu bằng \(0\) và \(1\) và các số tiếp theo được tạo bằng cách cộng hai số trước đó.

8 số Fibonacci đầu tiên là: \(0,\; 1,\; 1,\; 2,\; 3,\; 5,\; 8,\; 13\).

Và tính từ 0, số Fibonacci thứ \(4\)\(F(4)\) là \(3\).

Nói chung, đây là cách tạo số Fibonacci dựa trên hai số trước:

\[ F(n)=F(n-1)+F(n-2) \]

Vậy làm thế nào chúng ta có thể sử dụng Lập trình động để thiết kế một thuật toán tìm số Fibonacci thứ \(n\)th?

Không có quy tắc chính xác nào về cách thiết kế thuật toán bằng Lập trình động, nhưng đây là gợi ý có thể áp dụng được trong hầu hết các trường hợp:

  1. Kiểm tra xem sự cố có "các bài toán con chồng chéo" và "cấu trúc con tối ưu" hay không.
  2. Giải các bài toán con cơ bản nhất.
  3. Tìm cách kết hợp các lời giải của bài toán con lại với nhau để tạo thành lời giải cho các bài toán con mới.
  4. Viết thuật toán (quy trình từng bước).
  5. Thực hiện thuật toán (kiểm tra xem nó có hoạt động không).

Hãy làm nó.


Bước 1: Kiểm tra xem vấn đề có "các bài toán con chồng chéo" và "cấu trúc con tối ưu" hay không.

Trước khi thử tìm một thuật toán bằng Lập trình động, trước tiên chúng ta phải kiểm tra xem bài toán có hai thuộc tính "bài toán con chồng chéo" và "cấu trúc con tối ưu" hay không.

Các vấn đề phụ chồng chéo?

Đúng. Số Fibonacci thứ \(6\)là sự kết hợp của số Fibonacci thứ \(5\) và \(4\)th: \(8=5+3\). Và quy tắc này cũng áp dụng cho tất cả các số Fibonacci khác. Điều này cho thấy bài toán tìm số Fibonacci thứ \(n\)th có thể được chia thành các bài toán con.

Ngoài ra, các bài toán con trùng lặp vì \(F(5)\) dựa trên \(F(4)\) và \(F(3)\) và \(F(6)\) dựa trên \(F (5)\) và \(F(4)\).

\[ \begin{equation} \begin{aligned} F(5) {} & =\underline{F(4)}+F(3) \\ 5 & =\underline{3}+2 \\\\ & và \\\\ F(6) & =F(5)+\underline{F(4)} \\ 8 & =5+\underline{3} \end{aligned} \end{equation} \]

Bạn thấy không? Cả hai nghiệm của các bài toán con \(F(5)\) và \(F(6)\) đều được tạo bằng cách sử dụng nghiệm của \(F(4)\), và có nhiều trường hợp như vậy, do đó các bài toán con cũng trùng nhau .

Cấu trúc nền tảng tối ưu?

Đúng, dãy số Fibonacci có cấu trúc rất rõ ràng, vì hai số trước đó được cộng lại để tạo ra số Fibonacci tiếp theo và điều này đúng với tất cả các số Fibonacci ngoại trừ hai số đầu tiên. Điều này có nghĩa là chúng ta biết cách kết hợp một giải pháp bằng cách kết hợp các giải pháp cho các bài toán con.

Ta có thể kết luận bài toán tìm số Fibonacci thứ \(n\)thỏa mãn hai yêu cầu, nghĩa là ta có thể sử dụng Lập trình động để tìm ra thuật toán giải quyết bài toán.


Bước 2: Giải các bài toán con cơ bản nhất.

Bây giờ chúng ta có thể bắt đầu thử tìm một thuật toán bằng Lập trình động.

Việc giải các bài toán con cơ bản nhất trước tiên là nơi tốt để bắt đầu có ý tưởng về cách chạy thuật toán.

Trong bài toán tìm số Fibonacci thứ \(n\)th, việc tìm các bài toán con cơ bản nhất không khó lắm, vì chúng ta đã biết rằng

\[ F(0)=0 \\ F(1)=1 \\ F(2)=1 \\ F(3)=2 \\ F(4)=3 \\ F(5)=5 \\ F(6)=8 \\ ... \]


Bước 3: Tìm cách ghép các lời giải của bài toán con lại với nhau để tạo thành lời giải của bài toán con mới.

Ở bước này, đối với bài toán của chúng ta, cách ghép các bài toán con lại với nhau khá đơn giản, chúng ta chỉ cần cộng hai số Fibonacci trước đó để tìm số tiếp theo.

Vì vậy, ví dụ: số Fibonacci \(2\)nd được tạo bằng cách cộng hai số trước đó \(F(2)=F(1)+F(0)\), và đó cũng là quy tắc chung, như đã đề cập trước đó: \(F(n)=F(n-1)+F(n-2)\).

Lưu ý: Trong các bài toán khác, việc kết hợp lời giải của các bài toán con để tạo thành lời giải mới thường liên quan đến việc đưa ra các quyết định như "chúng ta nên chọn cách này hay cách này?" hoặc "chúng ta nên đưa mục này vào hay không?".


Bước 4: Viết thuật toán (quy trình từng bước).

Thay vì viết ngay văn bản cho thuật toán, có thể bạn nên thử viết một quy trình để giải quyết một vấn đề cụ thể trước tiên, chẳng hạn như tìm số Fibonacci thứ \(6\).

Để tham khảo, 8 số Fibonacci đầu tiên là: \(0,\; 1,\; 1,\; 2,\; 3,\; 5,\; \underline{8},\; 13\).

Tìm số Fibonacci thứ \(6\), chúng ta có thể bắt đầu với hai số đầu tiên \(0\) và \(1\), xuất hiện ở vị trí 0 và 1 trong dãy và đặt chúng vào một mảng, tại chỉ mục 0 và 1. Sau đó, chúng ta có thể cộng hai số đầu tiên trong mảng để tạo số tiếp theo và đẩy số mới đó làm phần tử mới vào mảng. Nếu chúng ta tiếp tục như vậy cho đến khi mảng dài 7 phần tử, chúng ta sẽ dừng và trả về F[6] . Điều đó sẽ hiệu quả, phải không?

Sau khi giải quyết vấn đề cụ thể ở trên, việc viết thuật toán thực tế trở nên dễ dàng hơn.

Thuật toán tìm số Fibonacci thứ \(n\), sử dụng Lập trình động làm phương pháp thiết kế, có thể được mô tả như sau:

Làm thế nào nó hoạt động:

  1. Tạo một mảng F , với các phần tử \(n+1\).
  2. Lưu trữ hai số Fibonacci đầu tiên F[0]=0F[1]=1 .
  3. Lưu phần tử tiếp theo F[2]=F[1]+F[0] và tiếp tục tạo các số Fibonacci mới như vậy cho đến khi giá trị trong F[n] được tạo.
  4. Trả về F[n] .

Bước 5: Thực hiện thuật toán (kiểm tra xem nó có hoạt động không)

Để triển khai thuật toán ở trên, chúng tôi giả sử rằng đối số n của hàm là một số dương (số Fibonacci thứ \(n\)), chúng tôi sử dụng vòng lặp for để tạo các số Fibonacci mới và chúng tôi trả về các trường hợp cơ sở F[0]F[1] ngay lập tức nếu hàm được gọi với đối số là 0 hoặc 1 .

Việc thực hiện thuật toán cũng có nghĩa là chúng ta có thể kiểm tra xem nó có hoạt động hay không.

Ví dụ

Tìm số Fibonacci thứ 6 bằng thuật toán mới của chúng tôi:

 def nth_fibo(n):     if n==0: return 0     if n==1: return 1      F = [None] * (n + 1)     F[0] = 0     F[1] = 1      for i in range(2, n + 1):         F[i] = F[i - 1] + F[i - 2]      return F[n] 
n = 6
result = nth_fibo(n)
print(f"The {n}th Fibonacci number is {result}")
Chạy ví dụ »

Nó đây rồi!

Chúng tôi đã sử dụng Lập trình động làm phương pháp thiết kế để tạo ra thuật toán tìm số Fibonacci thứ \(n\).

Chúng tôi cũng đã triển khai thuật toán để chứng minh rằng nó hoạt động và khi làm như vậy, chúng tôi đã vô tình sử dụng một kỹ thuật đã được thiết lập tốt trong Lập trình động được gọi là lập bảng , trong đó giải pháp được tìm thấy bằng cách giải các bài toán con từ dưới lên, sử dụng một số loại bảng.

Hơn nữa, chúng tôi đã tránh tính toán nhiều lần các bài toán con chồng chéo giống nhau, chẳng hạn như F[3] , mà cuối cùng chúng tôi có thể đã làm khác, chẳng hạn như với cách tiếp cận đệ quy bạo lực .

Một kỹ thuật khác được sử dụng trong Lập trình động được gọi là ghi nhớ . Trong trường hợp này, việc sử dụng tính năng ghi nhớ về cơ bản sẽ giải quyết vấn đề một cách đệ quy bằng vũ lực, nhưng lưu trữ các giải pháp của bài toán con cho lần sau khi thuật toán chạy để tránh thực hiện các phép tính tương tự nhiều lần.


Các kỹ thuật được sử dụng trong lập trình động

Có thể khó thiết kế một thuật toán bằng Lập trình động, nhưng khái niệm Lập trình động thực ra không khó đến thế: Giải quyết vấn đề, nhưng vì các bài toán con chồng lên nhau nên hãy thực hiện một cách thông minh sao cho chỉ cần giải quyết một bài toán con cụ thể. giải quyết một lần.

Để có thể sử dụng lời giải cho các bài toán con đã được giải quyết trước đó trong Lập trình động, các lời giải được tìm thấy trước đó phải được lưu trữ bằng cách nào đó và việc đó có thể được thực hiện bằng cách sử dụng tính năng ghi nhớ hoặc lập bảng .

Ghi nhớ là một kỹ thuật được sử dụng trong Lập trình động, trong đó giải pháp được tìm thấy theo cách đệ quy. Khi thuật toán chạy, giải pháp cho các bài toán con được lưu trữ và trước khi thử tính giải pháp cho một bài toán con, trước tiên nó sẽ kiểm tra xem giải pháp đó đã được tính toán chưa, để tránh thực hiện cùng một phép tính nhiều lần.

Kỹ thuật ghi nhớ được gọi là "từ trên xuống" vì lệnh gọi hàm ban đầu dành cho vấn đề chính và nó dẫn đến các lệnh gọi hàm mới để giải các bài toán con ngày càng nhỏ hơn.

Lập bảng là một kỹ thuật được sử dụng trong Lập trình động, trong đó lời giải cho các bài toán con chồng chéo được lưu trữ trong một bảng (mảng), bắt đầu bằng các bài toán con cơ bản nhất.

Kỹ thuật lập bảng không đệ quy và được gọi là "từ dưới lên" do cách xây dựng lời giải cuối cùng bằng cách giải các bài toán con cơ bản nhất trước tiên. Vì các lời giải của bài toán con cơ bản nhất được lưu trữ trong bảng trước nên khi giải một bài toán con sau dựa trên các bài toán con trước đó, thuật toán có thể chỉ cần chọn các lời giải này ngay từ bảng mà không cần tính toán lại.

Để hiểu rõ hơn về cách hoạt động của tính năng ghi nhớ và được coi là "từ trên xuống" cũng như cách hoạt động của việc lập bảng và "từ dưới lên", hãy xem hai hình ảnh bên dưới.

F(10) F(9) . . . . F(2) F(1) F(0)
Phương pháp lập bảng từ dưới lên để tìm số Fibonacci thứ 10.
F(10) F(8) F(6) F(7) F(9) F(7) F(8)
Phương pháp ghi nhớ từ trên xuống để tìm số Fibonacci thứ 10.

Như bạn có thể thấy trong các hình ảnh trên, phương pháp lập bảng bắt đầu ở dưới cùng bằng cách giải F(0) trước, trong khi phương pháp ghi nhớ bắt đầu ở trên cùng với F(10) và chia nó thành các bài toán con ngày càng nhỏ hơn từ đó.



×

Liên hệ bán hàng

Nếu bạn muốn sử dụng dịch vụ của Example.com.vn với tư cách là một tổ chức giáo dục, nhóm hoặc doanh nghiệp, hãy gửi email cho chúng tôi:
[email được bảo vệ]

Báo cáo lỗi

Nếu bạn muốn báo cáo lỗi hoặc nếu bạn muốn đưa ra đề xuất, hãy gửi email cho chúng tôi:
[email được bảo vệ]

Example.com.vn được tối ưu hóa cho việc học tập và đào tạo. Các ví dụ có thể được đơn giản hóa để cải thiện khả năng đọc và học. Các hướng dẫn, tài liệu tham khảo và ví dụ liên tục được xem xét để tránh sai sót, nhưng chúng tôi không thể đảm bảo tính chính xác hoàn toàn của mọi nội dung. Trong khi sử dụng W3Schools, bạn đồng ý đã đọc và chấp nhận các điều khoản sử dụng , chính sách cookie và quyền riêng tư của chúng tôi.

Bản quyền 1999-2024 của Refsnes Data. Đã đăng ký Bản quyền. Example.com.vn được cung cấp bởi W3.CSS .