1. Trang chủ
  2. » Giáo Dục - Đào Tạo

(SKKN mới NHẤT) sử DỤNG PHƢƠNG PHÁP QUY HOẠCH ĐỘNG để GIẢI một số bài TOÁN có TÍNH TRUY hồi TRONG NGÔN NGỮ lập TRÌNH c++

39 10 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Sử Dụng Phương Pháp Quy Hoạch Động Để Giải Một Số Bài Toán Có Tính Truy Hồi Trong Ngôn Ngữ Lập Trình C++
Tác giả Nguyễn Thị Thương, Hồ Văn Chiến
Trường học Trường THPT Phan Đăng Lưu
Chuyên ngành Tin học
Thể loại sáng kiến kinh nghiệm
Năm xuất bản 2021 - 2022
Thành phố Nghệ An
Định dạng
Số trang 39
Dung lượng 1,27 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Với mong muốn tìm ra các giải pháp tối ưu cho các bài toán này, chúng tôi mạnh dạn trình bày sáng kiến kinh nghiệm: SỬ DỤNG PHƯƠNG PHÁP QUY HOẠCH ĐỘNG ĐỂ GIẢI MỘT SỐ BÀI TOÁN CÓ TÍNH TR

Trang 1

SỞ GIÁO DỤC VÀ ĐÀO TẠO NGHỆ AN Đơn vị: Trường THPT Phan Đăng Lưu

SÁNG KIẾN KINH NGHIỆM

Có đính kèm:

Mô hình Phần mềm Phim ảnh Hiện vật khác

Năm học: 2021 - 2022

Trang 2

MỤC LỤC

Phần I ĐẶT VẤN ĐỀ 1

1 Lý do chọn đề tài 1

2 Mục tiêu, nhiệm vụ của đề tài 1

3 Đối tượng nghiên cứu 1

4 Phương pháp nghiên cứu 2

Phần II NỘI DUNG NGHIÊN CỨU 2

1.Cơ sở lý luận 2

2 Thực trạng vấn đề nghiên cứu 2

3 Nội dung vấn đề nghiên cứu 3

3.1 Tên chủ đề 3

3.2 Cơ sở lý thuyết 3

3.2.1 Khái niệm về phương pháp quy hoạch động 3

3.2.2 Các bước giải bài toán quy hoạch động 3

3.2.3 Biện pháp lựa chọn và cài đặt chương trình 4

3.3 Các bài tập áp dụng 7

3.3.1 Dạng bài toán về dãy con liên tiếp 7

3.3.2 Dạng bài toán về dãy con không liên tiếp 10

3.3.3 Dạng bài toán Dãy con có tổng bằng S 18

3.3.4 Dạng bài toán Biến đổi xâu 22

3.3.5 Dạng bài toán Ghép cặp 30

Phần III KẾT LUẬN VÀ KIẾN NGHỊ 36

3.1 Kết luận 36

3.2 Kiến nghị 36

TÀI LIỆU THAM KHẢO 37

Trang 3

Phụ huynh và các thế hệ học sinh sau này cũng đã bắt đầu chú trọng và đã chọn các nghành nghề liên quan đến công nghệ thông tin nhiều hơn

Tuy nhiên trong hệ thống giáo dục nước ta hiện nay môn Tin học chưa được quan tâm đúng với tầm quan trọng của nó Tin Học đang bị xem là môn phụ trong trường học dẫn đến học sinh ít đầu tư cho môn học này, gây ra không ít khó khăn cho giáo viên trong nhà trường và đặc biệt chọn đội ngũ học sinh giỏi Mặt khác môn Tin học có đặc thù riêng, học sinh giỏi đi thi chủ yếu chấm bài tự động trên phần mềm themis nên phụ thuộc lớn vào thời gian thực hiện (thời gian chạy) chương trình và giới hạn độ lớn dữ liệu mà bài toán yêu cầu Vì vậy lập trình ngoài việc chú ý đến giới hạn dữ liệu bài toán thì cần lựa chọn thuật toán tối ưu để đảm bảo yêu cầu bài toán đặt ra Vì vậy để giải bài toán trong Tin Học thường phải xác định được:

- Bài toán thuộc lớp nào

- Sử dụng phương pháp tối ưu nào để giải nó

Trong quá trình nghiên cứu và bồi dưỡng học sinh giỏi chúng tôi gặp khá nhiều bài toán về dãy con và bài toán xử lí xâu Đây là một nội dung khá phổ biến trong các đề thi học sinh giỏi và là một nội dung khá khó Với mong muốn tìm ra các giải pháp tối ưu cho các bài toán này, chúng tôi mạnh dạn trình bày sáng kiến kinh

nghiệm: SỬ DỤNG PHƯƠNG PHÁP QUY HOẠCH ĐỘNG ĐỂ GIẢI MỘT

SỐ BÀI TOÁN CÓ TÍNH TRUY HỒI TRONG NGÔN NGỮ LẬP TRÌNH C++

2 Mục tiêu, nhiệm vụ của đề tài:

Nhằm giúp học sinh đứng trước 1 bài toán, xác định được là bài toán đó có thể

áp dụng được quy hoạch động không và cách giải cụ thể như thế nào, đánh giá, so sánh được thời gian thực hiện chương trình (độ phức tạp của thuật toán) Cách nhận diện và lập công thức quy hoạch động

3 Đối tượng nghiên cứu:

Sử dụng phương pháp quy hoạch động để giải một số bài toán có tính truy hồi trong C++như: Tìm dãy con; đếm dãy con; Tính tổng dãy con; và các bài toán liên quan đến xâu như tìm xâu con chung dài nhất và biến đổi xâu

Trang 4

4 Phương pháp nghiên cứu:

Để trình bày sáng kiến kinh nghiệm này chúng tôi sử dụng kết hợp nhiều phương pháp như: Nghiên cứu tài liệu, nghiên cứu theo chuyên đề, thực nghiệm,

so sánh, phân tích kết quả thực nghiệm, ý kiến đóng góp của đồng nghiệp trong thực tiễn giảng dạy

Phần II NỘI DUNG NGHIÊN CỨU:

1 Cơ sở lý luận:

Sự phát triển như vũ bão của Tin học và những đóng góp lớn của Tin học trong

sự phát triển xã hội không thể phủ nhận được, đặc biệt trong dịp dịch Covid 19 vai trò của Tin học đã được khẳng định, mọi người dân nói chung và phụ huynh học sinh nói riêng đã nhìn thấy được vai trò quan trọng của Tin học trong mọi lĩnh vực kinh tế, văn hóa và giáo dục Chắc chắn mọi người đã có cái nhìn nhận khác và thấy môn Tin Học rất quan trọng

Xã hội phát triển, đòi hỏi Tin học cũng phát triển để đáp ứng nhu cầu của xã hội Để đáp ứng những đòi hỏi của sự phát triển đó phải có kế hoạch đào tạo bồi dưỡng những cá nhân có niềm say mê và có năng khiếu trong lĩnh vực tin học và trang bị vốn kiến thức cơ sở vững chắc, giúp cho mục tiêu đi trước đón đầu, rút ngắn khoảng cách về trình độ tin học giữa nước ta và thế giới

Trong quá trình nghiên cứu, giảng dạy, chúng ta gặp rất nhiều các bài tập toán tin Các bài tập dạng này rất phong phú và đa dạng Thực tế chưa có thuật toán hoàn chỉnh có thể áp dụng cho mọi bài toán Tuy nhiên người ta đã tìm ra một số thuật toán chung như: tham lam, quay lui, quy hoạch động, các giải thuật trên đồ thị Các thuật toán này có thể áp dụng để giải một lớp khá rộng các bài toán hay gặp trong thực tế Trong quá trình ôn thi học sinh giỏi của trường, việc truyền đạt các kiến thức về một số thuật toán như: quay lui, quy hoạch động, tham lam, các giải thuật trên đồ thị… là rất cần thiết cho học sinh để phát triển tư duy và lập trình giải các bài toán tin học Tạo lập và củng cố lòng say mê tìm hiểu và khám phá cho học sinh khi giải các bài toán tin

Trong quá trình dạy bồi dưỡng chúng tôi nhận thấy, nếu học sinh thực hiện tốt việc lựa chọn và cài đặt chương trình tối ưu khi giải các bài tập về dãy con và các bài tập xử lí xâu nói riêng và các bài tập lập trình nói chung thì chất lượng học sinh

giỏi sẽ được nâng cao

Trang 5

- Môn Tin học vẫn đang bị xem là môn “phụ”, không tham gia thi tốt nghiệp hay đại học cao đẳng vì thế môn Tin Học chưa nhận được sự quan tâm của nhà trường cũng như phụ huynh và học sinh

Mặt khác, để lập trình đòi hỏi học sinh phải có một kiến thức cơ bản tốt, phải có khả năng về tư duy và đam mê

Vì vậy động viên và tuyển chọn được các em vào đội tuyển học sinh giỏi môn tin học ở trường rất khó

Trong thực trạng đó chúng tôi muốn tìm hiểu, nghiên cứu, và truyền những kinh nghiệm, hiểu biết của mình để truyền lại đam mê cho những học sinh ham thích môn Tin học

3 Nội dung vấn đề nghiên cứu:

3.1 Tên chủ đề:

SỬ DỤNG PHƯƠNG PHÁP QUY HOẠCH ĐỘNG ĐỂ GIẢI MỘT SỐ BÀI TOÁN CÓ TÍNH TRUY HỒI TRONG NGÔN NGỮ LẬP TRÌNH C++

3.2 Cơ sở lý thuyết:

3.2.1 Khái niệm về phương pháp quy hoạch động:

Các thuật toán đệ quy có ưu điểm dễ cài đặt, tuy nhiên do bản chất của quá trình

đệ quy, các chương trình này thường kéo theo những đòi hỏi lớn về không gian bộ nhớ và một khối lượng tính toán khổng lồ, nên một thuật toán hiệu quả là cực kỳ cần thiết Và trong những trường hợp như vậy, quy hoạch động là một trong những thuật toán được lựa chọn nhiều nhất

Quy hoạch động (Dynamic programming) là một kỹ thuật nhằm đơn giản hóa việc tính toán các công thức truy hồi bằng cách lưu trữ toàn bộ hay một phần kết quả tính toán tại mỗi bước với mục đích sử dụng lại Bản chất của quy hoạch động

là thay thế mô hình tính toán “từ trên xuống” (Top-down) bằng mô hình tính toán

“từ dưới lên” (Bottom-up)

Từ “programming” ở đây không liên quan gì tới việc lập trình cho máy tính, đó

là một thuật ngữ mà các nhà toán học hay dùng để chỉ ra các bước chung trong việc giải quyết một dạng bài toán hay một lớp các vấn đề Không có một thuật toán tổng quát để giải tất cả các bài toán quy hoạch động

Mục đích của phần này là cung cấp một cách tiếp cận mới trong việc giải quyết các bài toán tối ưu mang bản chất đệ quy, đồng thời đưa ra các ví dụ từ dễ đến khó

để học sinh có thể làm quen và hình thành các kỹ năng trong việc tiếp cận các bài toán quy hoạch động

3.2.2 Các bước giải bài toán quy hoạch động:

Có 4 bước để giải 1 bài toán bằng quy hoạch động:

Bước 1: Xây dựng hàm mục tiêu:

Trang 6

Áp dụng nguyên lý tối ưu của Bellman ta phân rã bài toán ban đầu thành các bài toán con cùng dạng có kích thước nhỏ hơn, sao cho việc giải quyết các bài toán con một cấp phụ thuộc vào kết quả của các bài toán con trước đó

Bước 2: Xác định bài toán cơ sở:

Bài toán cơ sở là các bài toán con nhỏ nhất mà ta có thể biết ngay kết quả hoặc tính được kết quả dễ dàng Đây chính là cơ sở để tính nghiệm cho các bài toán cấp lớn hơn

Bước 3: Xây dựng công thức truy hồi:

Căn cứ vào ý nghĩa hàm mục tiêu, tìm mối liên hệ giữa các bài toán con các cấp, ta tiến hành xây dựng công thức tính kết quả của bài toán cấp i dựa vào kết quả của các bài toán con cấp trước nó Lời giải được lưu vào mảng 1 chiều hoặc mảng 2 chiều (gọi là bảng phương án)

Bước 4: Dựa vào bảng phương án, truy vết để tìm phương án tối ưu

3.2.3 Biện pháp lựa chọn và cài đặt chương trình:

Khi nào thì dùng thuật toán quy hoạch động:

Phương pháp quy hoạch động dùng để giải bài toán tối ưu có bản chất đệ quy, tức là việc tìm phương án tối ưu cho bài toán đó có thể đưa về tìm phương án tối

ưu của một số hữu hạn các bài toán con Đối với nhiều thuật toán đệ quy chúng ta

đã tìm hiểu, nguyên lý chia để trị (divide and conquer) thường đóng vai trò chủ đạo trong việc thiết kế thuật toán Để giải quyết một bài toán lớn, ta chia nó làm nhiều bài toán con cùng dạng với nó để có thể giải quyết độc lập Trong phương pháp quy hoạch động, nguyên lý này càng được thể hiện rõ: Khi không biết cần phải giải quyết những bài toán con nào, ta sẽ đi giải quyết tất cả các bài toán con và lưu trữ những lời giải hay đáp số của chúng với mục đích sử dụng lại theo một sự phối hợp nào đó để giải quyết những bài toán tổng quát hơn Đó chính là điểm khác nhau giữa Quy hoạch động và phép phân giải đệ quy và cũng là nội dung phương pháp quy hoạch động

Phép phân giải đệ quy bắt đầu từ bài toán lớn phân rã thành nhiều bài toán con

và đi giải từng bài toán con đó Việc giải từng bài toán con lại đưa về phép phân rã tiếp thành nhiều bài toán nhỏ hơn và lại đi giải tiếp bài toán nhỏ hơn đó bất kể nó

đã được giải hay chưa

Quy hoạch động bắt đầu từ việc giải tất cả các bài toán nhỏ nhất (bài toán cơ sở) để từ đó từng bước giải quyết những bài toán lớn hơn, cho tới khi giải được bài toán lớn nhất (bài toán ban đầu)

Trang 7

hợp lời giải của các bài toán con đó cho ta lời giải của bài toán lớn

 Vì quy hoạch động là đi giải tất cả các bài toán con, nên nếu không

đủ không gian vật lý lưu trữ lời giải (bộ nhớ, đĩa…) để phối hợp chúng thì

phương pháp quy hoạch động cũng không thể thực hiện được

 Quá trình từ bài toán cơ sở tìm ra lời giải bài toán ban đầu phải qua hữu hạn bước

Cài đặt chương trình:

Các bước cài đặt một chương trình bằng phương pháp quy hoạch động

Bước 1 Giải tất cả các bài toán cơ sở (thông thường rất dễ), lưu các lời giải vào

bảng phương án

Bước 2 Dùng công thức truy hồi phối hợp những lời giải của những bài toán

nhỏ đã lưu trong bảng phương án để tìm lời giải của những bài toán lớn hơn và lưu chúng vào bảng phương án Cho tới khi bài toán ban đầu tìm được lời giải

Bước 3 Dựa vào bảng phương án, truy vết tìm ra nghiệm tối ưu

Các hướng thực hiện quy hoạch động:

- Quy hoạch động ngược:

Phương pháp quy hoạch động ngược là phương pháp được sử dụng rộng rãi, vì

nó khá tương ứng với suy nghĩ tự nhiên của chúng ta Chúng ta đọc đề bài, suy nghĩ cách giải cho nó Cách giải đó yêu cầu phải giải những bài toán nhỏ hơn, như kiểu làm toán ngày phải chứng minh các bổ đề vậy Chúng ta tiếp tục suy nghĩ cho những bài toán con này, rồi tổng hợp để tìm ra lời giải cho bài toán lớn Quá trình

cứ tiếp tục như vậy, và quy hoạch động kiểu “ngược” này đang được xây dựng đúng như vậy

Ngoài ra, về mặt lập trình, kiểu quy hoạch động này có mối quan hệ tương đối gần gũi với đệ quy Một bài toán lớn được giải dựa vào các bài toán con tương tự nhau (và tương tự bài toán lớn) thì việc áp dụng đệ quy có thể là một phương pháp

dễ dàng để code Vì vậy, nhiều trường hợp, có thể coi quy hoạch động là một cách

để tối ưu phương pháp đệ quy để giải một bài toán

Ví dụ: Xâu con chung dài nhất

Cho hai xâu ký tự Tìm độ dài xâu con chung nhỏ nhất giữa chúng Ví dụ với 2 xâu "quetzalcoatl" và "tezcatlipoca" thì xâu con chung dài nhất sẽ là "ezaloa" với

độ dài 6

Với bài toán này, chúng ta sẽ lần lượt giải các bài toán con như sau:

Lấy i ký tự đầu tiên từ xâu thứ nhất và j ký tự đầu tiên từ xâu thứ hai và tìm độ dài xâu chung dài nhất giữa 2 xâu con được lấy ra đó Dễ dàng thấy được rằng, lời giải của mỗi bài toán con sẽ phụ thuộc vào i và j, L(i, j) Và bài toán lớn sẽ được

Trang 8

giải bằng cách lần lượt giải các bài toán con lần lượt từ L(0, 0) và tăng dần độ dài xâu được lấy ra cho đến khi chúng ta lấy ra toàn bộ xâu của đề bài

Chúng ta hãy bắt đầu lần lượt các bài toán con Đương nhiên, nếu một trong hai xâu là rỗng thì xâu con chung của chúng cũng rỗng Vậy L(0, j) = L(i, 0) = 0 Nếu

cả i và j đều dương, chúng ta cần suy xét một vài trường hợp

1 Nếu ký tự cuối cùng của xâu thứ nhất không có mặt trong xâu con chung dài nhất, nó có thể bị bỏ qua mà không ảnh hưởng gì đến kết quả Công thức ở đây sẽ

Trong cả ba trường hợp trên, chúng ta phải chọn ra trường hợp nào cho kết quả

là xâu con chung dài nhất (với bài toán này thì chỉ cần đưa ra độ dài đó là đủ)

- Quy hoạch động xuôi:

Ngoài kiểu quy hoạch động ngược này, có một kiểu quy hoạch động “xuôi” Tuy không phổ biến, kiểu quy hoạch động xuôi cũng khá khó áp dụng, nhưng quy hoạch động “xuôi” mang đến cho chúng ta nhiều tiện lợi Kiểu xuôi này cũng cần duyệt qua các bài toán con từ nhỏ đến lớn, nhưng với mỗi bài toán con, chúng ta tính toán kết quả và từ đó tìm cách thực hiện một số phép tính để giải bài toán lớn hơn Nghĩa là, với mỗi bài toán con, chúng ta sẽ nhìn về phía trước để xem phải giải bài toán tiếp theo như thế này từ bài toán hiện tại

Phương pháp này khó áp dụng hơn phương pháp ngược kia, và cũng không phải bài toán nào cũng áp dụng được Với mỗi bài toán, việc xác định bước tiếp theo tương đối khó khăn, thậm chí việc kiểm tra tính đúng sai của phương pháp cũng không hề dễ dàng

Như chúng ta đã thấy ở những phần trước, thông thường, mỗi bài toán cần phải giải bằng cách tổng hợp kết quả từ một vài bài toán con trước đó Vì vậy, cách quy hoạch động xuôi này chỉ sử dụng một bài toán con để tính toán trước bài toán tiếp theo sẽ chỉ cho ra một phần của kết quả chứ không phải kết quả cuối cùng Vì vậy,

để thực hiện quy hoạch động xuôi, việc điền sẵn một mảng các giá trị trung tính là điều bắt buộc (sau đó chúng ta sẽ cộng dồn kết quả vào mỗi khi giải được một bài toán con mới)

Ví dụ: Xâu con chung dài nhất: Với bài toán này, chúng ta có thể chọn giá trị trung tính là một số âm Chúng ta sẽ tìm cách quy hoạch động xuôi như sau:

Trang 9

 L(0,0) = 0 là bài toán với hai xâu rỗng

 Với mỗi bài toán L(i, j) chúng ta sẽ tìm cách tính toán kết quả cho các bài toán lớn hơn Lúc này, có 3 hướng phát triển tiếp:

1 Lấy thêm một ký tự từ xâu thứ nhất => Kết quả không thay đổi

2 Lấy thêm một ký tự từ xâu thứ hai => Kết quả cũng không thay đổi

3 Nếu ký tự tiếp theo của cả hai xâu giống nhau => Lấy tự từ này và độ dài xâu con chung tăng lên 1

3.3 Các bài tập áp dụng:

3.3.1 Dạng bài toán về dãy con liên tiếp:

Mô hình: Bài toán điển hình:

Cho dãy a1,a2, an (1 <= n <= 106) có giá trị tuyệt đối không quá 104 Yêu cầu:

Hãy lập trình tìm dãy con liên tiếp tăng dài nhất trong dãy a

Dữ liệu vào: Đọc từ file DAYCON1.INP:

Ta có công thức QHĐ để tính L(i) như sau:

+ Bài toán cơ sở: L[1] = 1

+ Xét a[i] (2≤i≤n):

 L[i]=1; (Với 1≤i≤ N và a[i] <a[i-1])

 L[i] = L[i-1] +1; (Với 1≤i≤ N và a[i] >a[i-1])

(độ dài đoạn con liên tiếp tăng sẽ nối thêm 1 đơn vị)

 Nếu a[i-1] >a[i] thì L[i] =1; (phần tử đầu cho dãy tăng mới)

Trang 10

Tính L[i] : Phần tử đang được xét là a[i] Ta tìm đến phần tử a[i-1]< a[i] có 1] Khi đó nếu bổ sung a[i] vào sau dãy con a[1] a[i-1] ta sẽ được dãy con tăng dần dài nhất xét từ a[1] a[i]

L[i-Kết quả: độ dài lớn nhất của dãy liên tiếp = giá trị lớn nhất của mảng L

Độ phức tạp của thuật toán này là o(n)

cin >> n; int res=0;

for (int i = 1; i <= n; i++) cin >> a[i];

L[1]=1;

for (int i = 2; i <= n; i++)

{if (a[i-1] < a[i] ) L[i] = L[i-1]+1;

Đề bài: Dãy con không giảm (Đề HSG tỉnh Bạc Liêu 2020-2021)

Cho số nguyên dương N và dãy số nguyên a1, a2, , aN có giá trị tuyệt đối không quá 103 Dãy không giảm là dãy số có số hạng trước không lớn hơn số hạng sau

Yêu cầu: Hãy lập trình tìm dãy con liên tiếp không giảm dài nhất trong dãy a

Dữ liệu vào: Đọc từ file CAU1.INP:

 Dòng đầu tiên chứa số nguyên dương N(2≤N≤104

)

Trang 11

 N dòng tiếp theo, mỗi dòng chứa một số nguyên là các phần tử của a

Dữ liệu ra: Ghi vào file CAU1.OUT một số nguyên dương duy nhất là độ dài của dãy con liên tiếp dài nhất tìm được

Độ dài đoạn con liên tiếp không giảm dài nhất là: max(L[])

+ Bài toán cơ sở: L[1] =1;

Trang 12

3.3.2 Dạng bài toán về dãy con không liên tiếp:

Mô hình: Bài toán điển hình:

Cho dãy a1,a2, an (1 <= n <= 103)

Yêu cầu: Hãy lập trình tìm dãy con tăng dài nhất trong dãy a

Dữ liệu vào: Đọc từ file DAYCON2.INP:

Dòng đầu tiên nhập số N

 Dòng tiếp theo nhập các số A1, A2, …, AN

Dữ liệu ra: Ghi vào file DAYCON2.OUT

 Dòng 1: một số nguyên dương duy nhất là độ dài của dãy con dài nhất tìm được

Dòng 2: Đưa ra dãy con dài nhất tìm được

Trang 13

Cách 1:

Công thức:

 Phân rã bài toán:

Ta bổ sung 2 phần tử “lính canh” là a[0]= -∞ vào đầu dãy và a[n+1] = +∞ vào cuối dãy Khi đó dãy con đơn điệu tăng dài nhất chắc chắn sẽ bắt đầu từ a[0] và kết thúc tại a[n]+1

→ Tổng quát: Cần tìm độ dài của dãy con tăng dài nhất từ a[i] →a[n+1]

 Xây dựng hàm mục tiêu:

- Gọi L[i] là độ dài của dãy con tăng dài nhất bắt đầu tại a[i] với (0≤i≤n+1)

- Suy ra kết quả của bài toán là: L[n+1] - 2

 Bài toán cơ sở: Ta dễ dàng thấy được L[n+1] =1; (Dãy con bắt đầu từ a[n+1] = -∞, dãy con này gồm 1 phần tử là -∞ nên L[n+1]=1

 Xây dựng công thức:

- Xét a[i]:

Nếu a[i] <a[j] (với 0≤i<j) thì L[i] = L[jmax] +1)

Dãy con đơn điệu tăng dài nhất bắt đầu từ a[i] sẽ được thành lập bằng cách lấy a[i] ghép vào đầu một trong những dãy con đơn điệu tăng dài nhất bắt đầu tại a[j]

mà a[i] < a[j] (i+1≤j≤n+1)

Vậy L[i] sẽ được tính: Xét tất cả các chỉ số j trong khoảng từ i+1 đến n+1 mà a[j] > a[i], chọn ra chỉ số jmaxcó L[jmax] lớn nhất

 Truy vết:

Tại bước xây dựng L, mỗi khi tính L[i] =L[jmax]+1, ta đặt T[i]=jmax, để lưu lại dãy con tăng dài nhất bắt đầu tại a[i] sẽ có phần tử thứ hai kế tiếp là a[jmax]

Sau khi xây dựng xong 2 mảng L và T:

- Bắt đầu từ phần tử đầu tiên i=T[0]

Trang 14

while( i != n+1) //Chừng nào chƣa duyệt đến aN+1

T[i] 2 4 3 5 7 6 7 9 9 11 11

Trang 15

 Phân rã bài toán:

Ta bổ sung 2 phần tử “lính canh” là a[0]= -∞ vào đầu dãy và a[n+1] = +∞ vào cuối dãy Khi đó dãy con đơn điệu tăng dài nhất chắc chắn sẽ bắt đầu từ a[0] và kết thúc tại a[n]+1

→ Cần tìm độ dài của dãy con tăng dài nhất từ a[0] →a[i]

 Xây dựng hàm mục tiêu:

- Gọi L[i] là độ dài của dãy con tăng dài nhất từ a[0] →a[i]

- Suy ra kết quả của bài toán là: L[n+1] - 2

 Bài toán cơ sở: Ta dễ dàng thấy đƣợc L[0] =1; L[1] =2 (Dãy con bắt đầu từ a[0]=-∞, dãy con này gồm 1 phần tử là -∞ nên L[0]=1 Phần tử tiếp theo L[1] chắc chắn thỏa mãn > -∞ nên dãy con tăng dài nhất lúc này L[1]=2)

Trang 16

 Xây dựng công thức:

- Xét a[i]:

Nếu a[j] <a[i] (với 0≤j<i) thì L[i] = max(L[i], L[j] +1)

(duyệt tất cả các a[j] ở trước a[i] nếu mà a[j] <a[i], độ dài dãy con dài nhất tại thời điểm đó sẽ được nối thêm 1 phần tử vào sau dãy con dài nhất trước đó

 Truy vết:

Tại bước xây dựng L, mỗi khi tính L[i] = L[j] + 1, ta đặt T[i] = j, để lưu lại dãy con tăng dài nhất bắt đầu tại a[i] sẽ có phần tử thứ hai kế tiếp là a[jmax]

Sau khi xây dựng xong 2 mảng L và T:

Ta tạo 1 mảng lưu các giá trị ta truy vết được

- Bắt đầu từ phần tử đầu tiên i=T[n+1]

- Sau đó thông báo các phần tử được chọn

Ví dụ: với A = (7, 4, 5, 8, 6, 7, 10, 9, 11, 8) Hai mảng L và T sau khi tính sẽ là:

Trang 17

for (int i=2; i<=n+1; i++)

for (int j=0; j<i; j++)

if (a[j] < a[i] && L[i] < L[j] + 1)

Trang 18

for (int i=x.size() - 1; i>0; i )

cout << x[i] << " ";

return 0;

}

Bài toán cùng dạng:

Đề bài: BCAKE (ĐỀ THI HSG TỈNH NGHỆ AN 2018)

An đã mua 𝑛 chiếc bánh, những chiếc bánh đƣợc đánh

số theo thứ tự từ 1 đến 𝑛, mỗi chiếc bánh có dạng hình trụ

và ta coi thể tích của chiếc bánh chính bằng thể tích của

hình trụ, đƣợc tính theo công thức v = π.r2.h Tuy nhiên

nếu chỉ để 𝑛 chiếc bánh đơn l thì không có gì đặc biệt

nên An muốn xếp những chiếc bánh thành một chiếc bánh

nhiều tầng, hơn nữa còn phải là một chiếc bánh nhiều

tầng có dạng tháp chổng ngƣợc Chiếc bánh thứ 𝑗 có thể

xếp trên chiếc bánh thứ 𝑖 nếu 𝑗 > 𝑖 và thể tích của chiếc

bánh thứ 𝑗 lớn hơn thể tích của chiếc bánh thứ 𝑖 Thể tích

của chiếc bánh nhiều tầng bằng tổng thể tích những chiếc

bánh đơn l Bạn hãy giúp An tính toán thể tích lớn nhất của chiếc bánh nhiều tầng

mà cậu có thể xếp đƣợc

Dữ liệu: Vào từ file BCAKE.INP

Dòng đầu tiên chứa số nguyên 𝑛 (1 ≤ 𝑛 ≤ 105

) 𝑛 dòng tiếp theo, mỗi dòng chứa 2 số nguyên 𝑟𝑖, hi (1 ≤ 𝑟𝑖 ≤ 104; 1 ≤ hi ≤ 104

) cách nhau bởi dấu cách, lần lƣợt

là bán kính và chiều cao của chiếc bánh thứ 𝑖

Kết quả: Ghi ra file BCAKE.OUT một số thực là thể tích lớn nhất tìm đƣợc,

Trang 19

#define inf int(1e9)

#define ll long long

for (int i=2; i<=n+1; i++)

for (int j=0; j<i; j++)

if ( v[j] < v[i] && L[i] < L[j] + v[i])

L[i] = L[j] + v[i];

cout << setprecision(3) <<fixed<<L[n+1] - inf <<"\n";

Ngày đăng: 03/07/2022, 17:13

HÌNH ẢNH LIÊN QUAN

Bảng phƣơng án là một mảng một chiề uL để lƣu trữ các giá trị của hàm QHĐ L[i]. Chƣơng trình tính các giá trị của mảng L nhƣ sau: - (SKKN mới NHẤT) sử DỤNG PHƢƠNG PHÁP QUY HOẠCH ĐỘNG để GIẢI một số bài TOÁN có TÍNH TRUY hồi TRONG NGÔN NGỮ lập TRÌNH c++
Bảng ph ƣơng án là một mảng một chiề uL để lƣu trữ các giá trị của hàm QHĐ L[i]. Chƣơng trình tính các giá trị của mảng L nhƣ sau: (Trang 10)
Mô hình: Bài toán điển hình: Cho dãy a1,a2,..an (1 &lt;= n &lt;= 10 3 ). - (SKKN mới NHẤT) sử DỤNG PHƢƠNG PHÁP QUY HOẠCH ĐỘNG để GIẢI một số bài TOÁN có TÍNH TRUY hồi TRONG NGÔN NGỮ lập TRÌNH c++
h ình: Bài toán điển hình: Cho dãy a1,a2,..an (1 &lt;= n &lt;= 10 3 ) (Trang 12)
3.3.2. Dạng bài toán về dãy con không liên tiếp: - (SKKN mới NHẤT) sử DỤNG PHƢƠNG PHÁP QUY HOẠCH ĐỘNG để GIẢI một số bài TOÁN có TÍNH TRUY hồi TRONG NGÔN NGỮ lập TRÌNH c++
3.3.2. Dạng bài toán về dãy con không liên tiếp: (Trang 12)
bảng xuống cò nS phần tử. - (SKKN mới NHẤT) sử DỤNG PHƢƠNG PHÁP QUY HOẠCH ĐỘNG để GIẢI một số bài TOÁN có TÍNH TRUY hồi TRONG NGÔN NGỮ lập TRÌNH c++
bảng xu ống cò nS phần tử (Trang 21)
Biến đổi xâu là một trong số bài toán điển hình minh họa dễ hiểu nhất cho việc sử dụng thuật toán quy hoạch động - (SKKN mới NHẤT) sử DỤNG PHƢƠNG PHÁP QUY HOẠCH ĐỘNG để GIẢI một số bài TOÁN có TÍNH TRUY hồi TRONG NGÔN NGỮ lập TRÌNH c++
i ến đổi xâu là một trong số bài toán điển hình minh họa dễ hiểu nhất cho việc sử dụng thuật toán quy hoạch động (Trang 24)
cout&lt;&lt;&#34;\nSo buoc: &#34;&lt;&lt;step&lt;&lt;&#34;\n&#34;; // in ra màn hình // Truy vết - (SKKN mới NHẤT) sử DỤNG PHƢƠNG PHÁP QUY HOẠCH ĐỘNG để GIẢI một số bài TOÁN có TÍNH TRUY hồi TRONG NGÔN NGỮ lập TRÌNH c++
cout &lt;&lt;&#34;\nSo buoc: &#34;&lt;&lt;step&lt;&lt;&#34;\n&#34;; // in ra màn hình // Truy vết (Trang 27)
Để dễ hiểu hơn chúng ta xem hình minh họa dƣới đây: - (SKKN mới NHẤT) sử DỤNG PHƢƠNG PHÁP QUY HOẠCH ĐỘNG để GIẢI một số bài TOÁN có TÍNH TRUY hồi TRONG NGÔN NGỮ lập TRÌNH c++
d ễ hiểu hơn chúng ta xem hình minh họa dƣới đây: (Trang 29)
Truy vết để tìm và in ra xâu con ra màn hình sẽ dựa vào bảng kết quả mà ta tìm đƣợc ở phần trên - (SKKN mới NHẤT) sử DỤNG PHƢƠNG PHÁP QUY HOẠCH ĐỘNG để GIẢI một số bài TOÁN có TÍNH TRUY hồi TRONG NGÔN NGỮ lập TRÌNH c++
ruy vết để tìm và in ra xâu con ra màn hình sẽ dựa vào bảng kết quả mà ta tìm đƣợc ở phần trên (Trang 30)
Mô hình: Bài toán điển hình: (Olympic Quốc tế năm 1999.) - (SKKN mới NHẤT) sử DỤNG PHƢƠNG PHÁP QUY HOẠCH ĐỘNG để GIẢI một số bài TOÁN có TÍNH TRUY hồi TRONG NGÔN NGỮ lập TRÌNH c++
h ình: Bài toán điển hình: (Olympic Quốc tế năm 1999.) (Trang 32)

TỪ KHÓA LIÊN QUAN

TRÍCH ĐOẠN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w