Quy hoạch động là một phương pháp giảm thời gian chạy của các thuật toán thể hiện các tính chất của các bài toán con gối nhau Overlapping subproblem và cấu trúc contối ưu Optimal substru
Lời giới thiệu
Hiện nay, công nghệ thông tin xuất hiện ở mọi nơi và phát triển nhanh chóng, góp phần nâng cao chất lượng cuộc sống con người Công nghệ này giúp các nhà khoa học thực hiện nghiên cứu đột phá nhờ khả năng tính toán và xử lý khối lượng công việc lớn của máy tính, có thể thực hiện hàng tỷ phép tính chỉ trong vài giây Nhiều phần mềm ra đời nhằm giúp con người giải quyết công việc một cách dễ dàng hơn, được phát triển bởi các lập trình viên dựa trên các ngôn ngữ lập trình khác nhau Trong đó, Pascal là một ngôn ngữ lập trình phù hợp để những người mới bắt đầu học lập trình dễ tiếp cận và phát triển kỹ năng.
Trong các trường trung học phổ thông hiện nay, nhiệm vụ đào tạo toàn diện và bồi dưỡng năng lực của học sinh là ưu tiên hàng đầu, trong đó kết quả bồi dưỡng học sinh giỏi là tiêu chí đánh giá chất lượng giáo dục Đối với giáo viên THPT, việc bồi dưỡng học sinh giỏi là một thách thức đòi hỏi sự hiểu biết sâu rộng về chuyên ngành và các phương pháp giảng dạy phù hợp Giáo viên bộ môn Tin học cần trang bị kiến thức về lập trình và áp dụng các phương pháp giảng dạy thuật toán hiệu quả để giúp học sinh tiếp thu và vận dụng tốt kiến thức Để đạt thành tích cao trong các kỳ thi học sinh giỏi tỉnh và cấp cao hơn, học sinh phải tích lũy lượng kiến thức sâu về lập trình, vượt quá chương trình phổ thông thông thường Nhiệm vụ của giáo viên là cung cấp thêm kiến thức và phương pháp lập trình phù hợp, như các thuật toán: đệ quy, quy hoạch động, chia để trị, vét cạn, tham lam, trong đó mỗi thuật toán phù hợp với từng lớp bài toán cụ thể Trong khoa học máy tính, đệ quy là một yếu tố then chốt giúp thiết kế nhiều thuật toán quan trọng và là cơ sở nền tảng của quy hoạch động.
Quy hoạch động là phương pháp giúp giảm thời gian chạy của các thuật toán bằng cách tận dụng tính chất các bài toán con gối nhau và cấu trúc con tối ưu, đặc biệt hiệu quả trong giải các bài toán tối ưu hoá rời rạc Trong các kỳ thi học sinh giỏi tỉnh và cao hơn, từ 30% đến 40% các bài thi yêu cầu ứng dụng quy hoạch động, do đây là những bài toán đòi hỏi tư duy lập trình cao và kiến thức vững vàng Vì các bài thi chú trọng đến thời gian chạy và bộ nhớ thực thi, nên lựa chọn thuật toán hiệu quả là yếu tố then chốt, trong đó quy hoạch động thường là phương pháp phù hợp nhất Chỉ cần làm tốt các bài toán này, học sinh gần như đã có thể tìm ra lời giải, tuy nhiên họ thường gặp khó khăn trong việc phân biệt và áp dụng đúng phương pháp quy hoạch động so với các phương pháp khác.
Việc giúp học sinh phổ thông phân biệt và nhận thức về sự ưu việt của quy hoạch động là một nhiệm vụ quan trọng trong giảng dạy Tin học Hiểu rõ các thuật toán quy hoạch động giúp học sinh tự tin phân tích bài toán và chọn phương pháp giải phù hợp, từ đó nâng cao thành tích học tập Là giáo viên dạy Tin học tại trường trung học phổ thông và có nhiều năm kinh nghiệm giảng dạy đội tuyển thi học sinh giỏi, tôi nhận thấy việc đào tạo về quy hoạch động trong thiết kế thuật toán là yếu tố không thể thiếu để chuẩn bị tốt cho các em học sinh tham gia đội tuyển và đạt thành tích xuất sắc.
Tôi chọn đề tài “Giúp học sinh tiếp cận với phương pháp quy hoạch động bằng một số bài toán đơn giản trong Tin học” nhằm mang đến tài liệu học tập có ích cho giáo viên, học sinh và những ai quan tâm đến lĩnh vực này Hy vọng đề tài sẽ góp phần nâng cao hiểu biết của các em về phương pháp quy hoạch động, giúp các em vận dụng hiệu quả trong giải quyết các bài toán trong môn Tin học Đây sẽ là nguồn tài liệu hữu ích, hỗ trợ quá trình học tập và giảng dạy, góp phần thúc đẩy phát triển tư duy logic và năng lực giải quyết vấn đề của học sinh.
Tên sáng kiến
Giúp học sinh tiếp cận với phương pháp quy hoạch động bằng một số bài toán đơn giản trong Tin học.
Tác giả sáng kiến
- Họ và tên: Nguyễn Thị Hà
- Địa chỉ tác giả sáng kiến: Xã Đại Đồng – huyện Vĩnh Tường – tỉnh Vĩnh Phúc
- E_mail: nguyenthiha.gvnguyenvietxuan@vinhphuc.edu.vn
NỘI DUNG SÁNG KIẾN KINH NGHIỆM
Một số khái niệm cơ bản về phương pháp quy hoạch động
* Quy hoạch động (Dynamic Programming) là một phương pháp rất hiệu quả giải nhiều bài toán tin học, đặc biệt là những bài toán tối ưu.
Quy hoạch động trong ngành khoa học máy tính là phương pháp giảm thời gian chạy của các thuật toán Nó giúp tối ưu hóa hiệu suất bằng cách lưu trữ các kết quả trung gian, qua đó thể hiện rõ các tính chất của các bài toán con gối nhau Phương pháp này rất hữu ích trong việc giải quyết các bài toán phức tạp với các phần tử lồng nhau, nâng cao hiệu quả tính toán và tiết kiệm thời gian xử lý.
(Overlapping subproblem) và cấu trúc con tối ưu (Optimal substructure)
Phương pháp quy hoạch động bắt đầu bằng cách giải các bài toán nhỏ nhất (bài toán cơ sở), từ đó xây dựng các giải pháp cho các bài toán lớn hơn cho đến khi hoàn thành bài toán lớn nhất ban đầu Nguyên tắc cốt lõi của quy hoạch động là tránh tính toán lại các bài toán con đã được giải, thể hiện sức mạnh của nguyên lý chia để trị một cách tối ưu Phương pháp này giúp tối ưu hóa quá trình giải quyết các bài toán phức tạp thông qua việc lưu trữ và sử dụng lại các kết quả trung gian, làm giảm công sức tính toán và nâng cao hiệu quả.
* Một bài toán P muốn giải bằng phương pháp quy hoạch động cần có 2 đặc điểm sau:
Bài toán P tuân thủ nguyên lý tối ưu Bellman, cho phép sử dụng lời giải tối ưu của các bài toán con ở mức thấp nhất để xây dựng dần lời giải tối ưu cho các bài toán con ở cấp cao hơn Nguyên tắc này đóng vai trò cốt lõi trong quá trình tối ưu hoá, giúp tìm ra giải pháp tối ưu cuối cùng cho bài toán P hiệu quả hơn Nhờ vào nguyên lý Bellman, các thuật toán động lực có thể xác định các bước tối ưu liên tiếp dựa trên lời giải của các bài toán con, đảm bảo tính tối ưu toàn diện của bài toán tổng thể.
- Bài toán P có các bài toán con phủ chồng lên nhau, nghĩa là không gian bài toán con “hẹp” không tạo dạng hình cây.
1.2 Các bước giải quyết bài toán bằng phương pháp quy hoạch động
Trong bước đầu tiên, cần xây dựng hàm mục tiêu dựa trên nguyên lý tối ưu của Bellman, giúp phân rã bài toán ban đầu thành các bài toán con cùng cấu trúc Các bài toán con cấp i sẽ phụ thuộc vào kết quả của các bài toán cấp trước, đảm bảo quá trình giải quyết theo phương pháp động lực lập trình Cụ thể, nhiệm vụ của bước này là xác định hàm mục tiêu F(i), đại diện cho nghiệm tối ưu của bài toán con cấp i để hướng dẫn quá trình giải quyết toàn bộ bài toán một cách hiệu quả và logic.
- Bước 2: Xác định các bài toán cơ sở
Bài toán cơ sở là các bài toán con nhỏ nhất, có thể biết ngay kết quả hoặc dễ dàng tính toán Chúng đóng vai trò then chốt làm nền tảng giúp xác định nghiệm của các bài toán cấp cao hơn Việc hiểu rõ các bài toán cơ sở là bước quan trọng trong quá trình giải các bài toán phức tạp hơn.
- Bước 3: Xây dựng công thức truy hồi
Dựa trên ý nghĩa của hàm mục tiêu, ta xác định mối quan hệ giữa các bài toán con theo từng cấp độ Quá trình này giúp xây dựng công thức tính kết quả của bài toán cấp i dựa trên kết quả của các bài toán con cấp trước đó Việc này đảm bảo tính nhất quán và tối ưu hóa quá trình giải quyết bài toán lớn thông qua các phép tính trung gian Áp dụng phương pháp này còn giúp nâng cao hiệu quả tính toán và tối ưu hóa kết quả cuối cùng cho toàn bộ bài toán.
- Bước 4: Lập bảng phương án
Sử dụng công thức truy hồi và nghiệm các bài toán cơ sở tính nghiệm tất cả các bài toán con và lưu trữ chúng vào bảng phương án.
- Bước 5: Kết luận nghiệm của bài toán
Dựa vào bảng phương án chỉ ra nghiệm của bài toán Các bước giải quyết trên tuy rất cụ thể nhưng vẫn trừu tượng đối với học sinh.
Bài toán 1: Tính a n (n là số nguyên dương)
- Bước 1: Hàm mục tiêu: f(i) là lũy thừa của a i
- Bước 2: Các bài toán cơ sở: f(0) = 1;
- Bước 3: Công thức truy hồi: f(i) = a* f(i-1)
- Bước 5: Nghiệm f(n) của bài toán
- Bước 1: Hàm mục tiêu: f(i) là giai thừa của số i
- Bước 2: Các bài toán cơ sở: f (0) = 1; f(1) = 1
- Bước 3: Công thức truy hồi: f(i) = i* f(i-1)
- Bước 5: Nghiệm F(n) của bài toán
Bài toán 3: Tìm số Fibonaci thứ N?
- Bước 1: Hàm mục tiêu: f(i) là số fibonaci thứ i.
- Bước 2: Các bài toán cơ sở: f(0) = 1; f(1) = 1
- Bước 3: Công thức truy hồi: f (i) = f(i-1) + f(i-2)
- Bước 5: Nghiệm f(n) của bài toán
Bài toán 4: Tháp Hà Nội
Chuyển n chiếc đĩa từ cọc 1 sang cọc 2 theo thứ tự từ lớn đến nhỏ có sử dụng cọc
3 làm cọc trung gian Mỗi lần di chuyển được 1 đĩa Và đĩa đĩa lớn phải ở dưới đĩa nhỏ
- Bước 2: Các bài toán cơ sở: f(1): = 1
- Bước 3: Công thức truy hồi: f(i):=2*f(i-1)+1
- Bước 5: Nghiệm f(n) của bài toán
Bài toán 5: Bài toán cái túi
Trong siêu thị có n gói hàng (n 1, it returns 2 * thaphanoi(n-1) + 1 Both approaches efficiently determine the minimum number of moves required to solve the Tower of Hanoi puzzle for n disks.
Ví dụ 5: Bài toán cái túi
Trong siêu thị có n gói hàng (n c[i,j]) then f[i,j]:=f[i-1,j-w[i]]
+v[i]; end; end; begin inc(dem); s:=s+v[f[i1]]; s1:=s1+w[f[i1]]; if s1>m then exit; end; if s>max then max:=s; end;
2.2 Phương pháp quy hoạch động và phương pháp vét cạn
Quy hoạch động Vét cạn
- Quy hoạch động là tìm một kĩ thuật tìm kết quả trước thông qua một kết quả có sẵn hoặc được tìm thấy
- Ưu điểm là chạy rất nhanh
- Nhược điểm của nó là rất khó tìm ra thuật toán, với một số bài toán có thể sẽ không có thuật toán quy hoạch động.
- Vét cạn là một trong những thuật toán giải bài toán tối ưu
Thuật toán vét cạn là phương pháp tìm ra phương án tối ưu của bài toán bằng cách duyệt tất cả các khả năng trong tập hợp các phương án, giúp đảm bảo tìm ra kết quả chính xác Tuy nhiên, với không gian các phương án lớn, thuật toán vét cạn có độ phức tạp cao, thường là hàm mũ, gây tốn nhiều thời gian tính toán Trong khi đó, các phương pháp quy hoạch động có độ phức tạp đa thức, mang lại hiệu quả và khả năng thực thi cao hơn Do đó, việc áp dụng thuật toán vét cạn không đảm bảo về mặt thời gian và kỹ thuật trong các bài toán lớn hoặc phức tạp.
Vét cạn là xét toàn bộ trường hợp, rồi tìm ra kết quả.
- Ưu điểm của vét cạn là chắc chắn tìm ra lời giải (nếu có)
- Nhược điểm của nó là có thể chạy quá lâu, vượt mức thời gian cho phép
Vét cạn, theo nghĩa thông thường, là việc xét hết tất cả các đối tượng hoặc trường hợp có thể xảy ra Trong lập trình, vét cạn là kỹ thuật được sử dụng khi không còn phương pháp tối ưu nào khác để giải quyết vấn đề Phương pháp vét cạn giúp đảm bảo mọi khả năng đã được kiểm tra, từ đó chọn ra giải pháp tối ưu nhất cho bài toán Đây là kỹ thuật quan trọng để xử lý các bài toán phức tạp, đặc biệt khi các phương pháp khác không mang lại hiệu quả cao.
Cài đặt chương trình cho một số bài toán đơn giản thường gặp
Trong đề tài này, các bài toán được chọn đều là những bài toán đơn giản, dễ dàng xác định phương pháp giải, chủ yếu là đệ quy hoặc quy hoạch động Phần ví dụ trong SKKN tập trung vào mối quan hệ giữa hai phương pháp này, giúp người học dễ dàng so sánh và hiểu rõ hơn Để nâng cao khả năng phân biệt và nhận diện ưu điểm của từng phương pháp, mỗi bài tập đều có thêm biến “đếm” để đếm số lần lặp khi chạy thử cùng các bộ dữ liệu, từ đó giúp người học dễ nhận biết được độ ngắn gọn, hiệu quả của quy hoạch động so với đệ quy.
Ví dụ 1: Bài toán tính a n (n là số nguyên dương)
Cách xác định bài toán
- Output: giá trị a n Ý tưởng của bài toán
- Ta thấy n = 0 thì f(0) =1 n = 1 thì f(1) = a n = 2 thì f(2) = f(1)*a n = 3 thì f(3) = f(2)*a
- Trong bài toán này có giá trị chặn là n = 0
The article discusses an algorithmic method known as the QHĐ method, which utilizes the Quỹ Hệ Đếm (QHĐ) technique It involves implementing recursive functions and array-based computations to determine specific mathematical properties For example, a function called "lthua" calculates the factorial of a number using a loop that multiplies consecutive integers, storing the results in an array This approach enables efficient computation of large factorials, which is essential for advanced mathematical and programming applications Incorporating these techniques into algorithm design enhances performance and accuracy in solving complex problems related to number theory and combinatorics.
BEGIN clrscr; assign(g,'nhap.inp'); reset(g); dem:=0;
The program begins by reading the input values for variables a and n, then closes the input stream to proceed with calculations It calls the function lthua(a, n) to perform the necessary computations related to the iterative process The results are then written to an output file named 'xuat.out', starting with a descriptive header indicating that the remaining steps are calculated using the QHD method The program outputs the number of iterations, denoted as 'dem', and the result of the lthua(a, n) function, providing a clear summary of the computation.
END if n =0 then lthua:=1 else lthua:=a*lthua(a,n-1); end;
BEGIN clrscr; dem:=0; assign(f,'nhap.inp'); reset(f);
The program prompts the user to input values for variables a and n, then reads these inputs along with data from a file After processing, it closes the input file and prepares an output file named 'xuat.out' to record the results The program calculates the power of a raised to n using a recursive method, measuring the number of iterations involved Finally, it writes the computation results, including the total number of recursive calls and the calculated power, into the output file for the user to review.
Phân tích kết quả thử nghiệm cho thấy chương trình sử dụng phương pháp quy hoạch động (QHĐ) hoạt động hiệu quả hơn so với đệ quy, với số lần lặp chỉ là 10 so với 11 lượt của đệ quy Điều này chứng tỏ rằng phương pháp quy hoạch động tiết kiệm số lần lặp, nâng cao hiệu suất thực thi của chương trình.
Ví dụ 2: Tính n! (n là số nguyên dương)
Cách xác định bài toán
- Output: giá trị giai thừa của n Ý tưởng của bài toán
- Ta thấy n = 0 thì f(0) =1 n = 1 thì f(1) = 1 n = 2 thì f(2) = f(1)*2 n = 3 thì f(3) = f(2)*3
- Trong bài toán này có hai giá trị chặn là n = 0 và n = 1
Phương pháp QHĐ Phương pháp ĐQ
Uses crt; var n,i,dem:longint; g:text;
Uses crt; var dem,n:longint; f:text; f:array[0 100] of int64; function gthua(n:longint):int64; begin f[1]:=1; for i:= 2 to n do begin dem:+1; f[i]:=i*f[i-1]; end; exit(f[n]); end;
This article demonstrates how to compute the factorial of a number using a structured programming approach The program reads an input value 'n' from the file 'nhap.inp' and then calculates its factorial through the function 'gthua(n)' After computation, the results are written to the output file 'xuat.out', including the number of iterations 'dem' and the factorial value of 'n' This method exemplifies effective use of file handling and loop structures to perform factorial calculations in programming.
END. function gthua(n:longint):int64; begin dem:+1; if n