intTypePromotion=1
zunia.vn Tuyển sinh 2024 dành cho Gen-Z zunia.vn zunia.vn
ADSENSE

Bài giảng Thuật toán ứng dụng: Bài thực hành số 3 - TS. Đinh Viết Sang

Chia sẻ: _ _ | Ngày: | Loại File: PDF | Số trang:24

3
lượt xem
2
download
 
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Bài giảng "Thuật toán ứng dụng - Bài thực hành số 3" tập trung vào việc thực hành với ba thuật toán: EKO, PIE và FIBWORDS. Bài thực hành này giúp sinh viên củng cố kỹ năng lập trình và áp dụng các thuật toán vào việc giải quyết các bài toán cụ thể. Mục tiêu là giúp sinh viên hiểu sâu hơn về thiết kế và triển khai thuật toán. Mời các bạn cùng tham khảo!

Chủ đề:
Lưu

Nội dung Text: Bài giảng Thuật toán ứng dụng: Bài thực hành số 3 - TS. Đinh Viết Sang

  1. Thuật toán ứng dụng Bài thực hành số 3 Giảng viên: TS. Đinh Viết Sang Trợ giảng: Nguyễn Trung Hiếu Email: hieu.nt164813@sis.hust.edu.vn Viện Công nghệ thông tin & truyền thông Đại học Bách khoa Hà Nội 19/04/2020
  2. Nội dung EKO PIE FIBWORDS
  3. EKO Cho n cái cây có chiều cao khác nhau a1 , a2 , ...an Có thể thực hiện một phát cắt độ cao h với tất cả các cây. Số lượng gỗ thu được là phần chóp của các cây cao hơn h. Tìm h lớn nhất có thể để số lượng gỗ thu được tối thiểu là m.
  4. Ví dụ Có 4 cây 20, 15, 10, 17, lượng gỗ tối thiểu cần cắt là 7.
  5. Ví dụ Chọn h = 15 → số lượng gỗ thu được ở mỗi cây là 5, 0, 0, 2. Tổng lượng gỗ thu được là 7. Vậy chiều cao lớn nhất có thể cắt được là 15
  6. Thuật toán Thuật toán 1: Duyệt tất cả các giá trị h ∈ {0, max(ai )}. Độ phức tạp: O(max(ai ) × n). Thuật toán 2: Tìm kiếm nhị phân giá trị h. Độ phức tạp O(log (max(ai )) × n)
  7. Code 1 long long count_wood ( int height ) { 2 long long sum = 0; 3 for ( int i = 1; i height ) 5 sum += a [ i ] - height ; 6 return sum ; 7 } 8 9 int main { 10 int l = 0 , r = max (r , a [ i ]); 11 12 while ( r - l > 1) { 13 int mid = ( l + r ) / 2; 14 if ( count_wood ( mid ) >= m ) l = mid ; 15 else r = mid ; 16 } 17 cout
  8. PIE Có N cái bánh và F + 1 người. Bánh thứ i có bán kính ri và chiều cao là 1. Mỗi người chỉ được nhận một miếng bánh từ một chiếc bánh. Cần chia bánh sao cho mọi người có lượng bánh bằng nhau (có thể bỏ qua vụn bánh). Tìm lượng bánh lớn nhất mỗi người nhận được.
  9. Ví dụ Giả sử có 3 cái bánh có bán kính lần lượt là 2; 1; 1.5 Cần chia 3 cái bánh trên cho 7 người Cách chia sau là tối ưu, mỗi người nhận được một phần là π
  10. Thuật toán Gọi p[i] là số người ăn chiếc bánh thứ i. Lượng bánh mỗi người nhận được là mini { V [i] } với V [i] là thể tích của chiếc p[i] bánh thứ i. Cách 1 - Tìm kiếm theo mảng p: Tìm kiếm vét cạn mọi giá trị của p. Cách 2 - Tìm kiếm theo lượng bánh mỗi người nhận được: Thử từng kết quả, với mỗi kết quả, kiểm tra xem có thể chia bánh cho tối đa bao nhiêu người. Tối ưu cách 2: Sử dụng thuật toán tìm kiếm nhị phân để tìm kiếm kết quả.
  11. Code 19 20 int count_pie ( int m ) { 21 int cnt = 0; 22 23 for ( int i = 1; i eps ) 32 double m = ( l + r ) / 2; 33 if ( count_pie ( m ) > F ) l = m ; 34 else r = m ; 35 } 36 }
  12. FIBWORDS Dãy Fibonacci Words của xâu nhị phân được định nghĩa như sau:  0,  if n = 0 F (n) = 1, if n = 1  F (n − 1) + F (n − 2), if n ≥ 2  Cho n và một xâu nhị phân p. Đếm số lần p xuất hiện trong F (n) (các lần xuất hiện này có thể chồng lên nhau). Giới hạn: 0 ≤ n ≤ 100, p có không quá 100000 ký tự, kết quả không vượt quá 263 .
  13. Example F6 = 101 1102 103 1104 1105
  14. Thuật toán trực tiếp Sinh xâu F (n) ( O(n) ). Duyệt qua toàn bộ vị trí i của xâu Fn . Coi vị trí i là vị trí bắt đầu của xâu p. So khớp xâu p với xâu Fn [i, i + len(p) − 1]. ĐPT: O(len(Fn ) ∗ len(p))
  15. Thuật toán trực tiếp Sinh xâu F (n) ( O(n) ). Duyệt qua toàn bộ vị trí i của xâu Fn . Coi vị trí i là vị trí bắt đầu của xâu p. So khớp xâu p với xâu Fn [i, i + len(p) − 1]. ĐPT: O(len(Fn ) ∗ len(p)) Vấn đề: n → 100 ⇒ len(Fn ) → 354224848179261915075 Không đủ bộ nhớ để lưu. Quá thời gian.
  16. Cải tiến Nhận xét: Phân loại 3 trường hợp p xuất hiện trong Fn : TH1: Nằm hoàn toàn trong Fn−1 . TH2: Nằm hoàn toàn trong Fn−2 . TH3: Nằm ở giữa nửa đầu trong Fn−1 và nửa sau trong Fn−2 .
  17. Cải tiến Tính số lượng p xuất hiện trong trường hợp 1 (Fn−1 ) và 2 (Fn−2 ). → Một bài toán con của bài toán tính số lần xuất hiện p trong Fn . Ta có thể giả sử đã giải quyết các bài toán con này rồi. Sau đó nếu tìm được công thức tính tổng quát cho Fn . Ta có thể quay lui để áp dụng công thức đó trên Fn−1 và Fn−2
  18. Cải tiến Trong trường hợp này p sẽ nằm trong khoảng (len(Fn−1 ) − len(p), len(Fn−1 ) + len(p)). Do vậy điểm đầu của p chỉ phải xét từ len(Fn−1 ) − len(p) + 1 → len(Fn−1 ) − 1. Câu hỏi là làm sao để ta xây dựng được khoảng (len(Fn−1 ) − len(p), len(Fn−1 ) + len(p))
  19. Cải tiến suffix(Fn−1 ) = suffix(Fn−3 ) = suffix(Fn−5 ) = .... prefix(Fn−2 ) = prefix(Fn−3 ) = prefix(Fn−4 ) = .... Chúng ta chỉ cần lưu 2 suffix (một cho n lẻ một cho n chẵn) có độ dài lớn hơn p và một prefix có độ dài lớn hơn p.
  20. Cải tiến Độ phức tạp thuật toán TH3 ta mất O(p 2 ) để tính tất cả các trường hợp. Để tính Fn ta cần tính Fn−1 , Fn−2 , ...F1 . Nếu ta dùng mảng lưu lại giá trị tính được thì đpt sẽ là O(n). → ĐPT tổng thể là : O(n ∗ p 2 ). Với n ≤ 100, |q| ≤ 105 thì phương pháp này chưa đủ để full. Nhưng với mục đích training thì O(n ∗ p 2 ) đủ để full bài trên Codeforces.
ADSENSE

CÓ THỂ BẠN MUỐN DOWNLOAD

 

Đồng bộ tài khoản
2=>2