Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 28 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
28
Dung lượng
77 KB
Nội dung
CÁC KỸ THUẬT CƠ BẢN ĐỂ TĂNG TỐC CHƯƠNG TRÌNH Việc lưu trữ thơng tin cần nhớ cho lấy lại chúng cách nhanh kỹ để có chương trình hiệu Tuy việc nhớ lưu trữ lại địi hỏi nhạy bén tốn học học sinh Điều lại hình thành sau học sinh tiếp xúc với hệ thống toán tổ chức cẩn thận Hệ thống giúp học sinh xây dựng thói quen tư kỹ thuật lập trình Dưới đây, tơi trình bày hệ thống tập phân loại kỹ lưỡng qua nhiều năm giảng dạy nhằm mục đích hình thành cho em kỹ nói Kỹ thuật nhớ Đây kỹ thuật đơn giản, thông tin cần nhớ lưu trữ vào mảng vị trí thích hợp Khi cần, việc lấy thơng tin khoảng thời gian O(1) 6 Bài toán 1: Cho mảng n số nguyên dương a1, a2, , an (n≤10 , ai≤10 ) số nguyên dương S (S≤10 ) Hãy đếm xem có cặp (ai,aj) thỏa mãn ai+aj=S Thuật toán O(n ) đơn giản đề giải toán là: ds:=0; for j:=1 to n for i:=1 to j-1 if a[i]+a[j]=S then ds:=ds+1; writeln(ds); Để cải tiến, xem xét đẳng thức điều kiện a[i]+a[j]=S Nếu j cố định a[i]=S-a[j] cố định Và thấy vòng lặp bên chẳng qua đếm xem có phần tử S-a[j] Vậy ta nhớ số lượng xem khơng cần vòng lặp bên để đếm nữa! Để ý đến điều kiện đầu 1≤a[i]≤10 ta hồn tồn lập mảng nhớ: var c: array[1 1000000] of longint; với c[x] số lượng phần tử x xuất Ta có chương trình hiệu để giải sau: fillchar(c,sizeof(c),0); for j:=1 to n begin if (S-a[j]>0) then inc(ds,c[S-a[j]]); inc(c[a[j]]); end; Thuật toán có độ phức tạp O(n) đáp ứng dược yêu cầu toán đề mặt thời gian Tuy nhiên thấy chi phí nhớ tăng lên Có thể nhận xét điều để học sinh thấy muốn có chương trình chạy nhanh chi phí nhớ phải tốn Bài toán 2: Cho dãy số a1, a2, , an (1≤n≤10 , 109 ) Hãy tìm dãy dãy số cho gồm phần tử liên tiếp cho tổng phần tử dãy lớn Đây toán điển hình cho việc cải tiến chương trình cho mức độ hiệu ngày cao Ta xét thuật toán đơn giản để giải toán có độ phức tạp O(n ): ds:=0; for j:=1 to n for i:=1 to j begin T:=0; for k:=I to j T:=T+a[k]; if T>ds then ds:=T; end; Thuật tốn hồn tồn tự nhiên Tuy nhiên với độ phức tạp O(n ) cho kết thời gian giây n≤100 Cần phải có thuật tốn tinh tế Nhận xét để tính tổng T=a[i]+a[i+1]+…a[j] ta viết T=(a[1]+a[2]+ …+a[j])-(a[1]+a[2]+…+a[i-1]) = s[j]-s[i-1] s[k]=a[1]+…a[k] Bằng cách chuẩn bị trước mảng S O(n) ta thay vịng lặp thuật tốn lệnh Ta có chương trình cải tiến sau: ds:=a[1]; s[0]:=0; for i:=1 to n s[i]:=s[i-1]+a[i]; for j:=1 to n for i:=1 to j if s[j]-s[i-1]>ds then ds:=s[j]-s[i-1]; Độ phức tạp thuật toán thứ hai O(n ) dùng thuật tốn giải toán với n≤2000 Để tăng tốc chương trình nữa, đến lại sử dụng kỹ thuật nhớ toán Xét vịng lặp (i) Nếu j cố định vịng lặp chẳng qua tìm số I để s[j]-s[i-1] đạt giá trị lớn Điều tương đương với việc tìm giá trị nhỏ s[i-1] với i=1,2,…,j tìm giá tị nhỏ s[0],s[1],…,s[j-1] Bằng cách dùng thêm biến để lưu giá trị nhỏ có thuật tốn O(n) đáp ứng yêu cầu toán sau: s[0]:=0; for i:=1 to n s[i]:=s[i-1]+a[i]; ds:=a[1]; min:=0; for j:=1 to n begin if s[j]-min>ds then ds:=s[j]-min; if s[j]ds then ds:=b[k]-min if min>b[k] then min:=b[k]; end; end; Độ phức tạp thuật toán O(m n) Một điều thú vị kỹ thuật cố định hàng hàng kỹ thuật phổ biến để đưa việc giải toán hai chiều thành toán chiều Bài toán 4: Cho dãy nhị phân độ dài n Hãy đếm xem có dãy dãy cho có số lượng số số lượng số Với việc làm quen kỹ thuật tính tổng đoạn [i,j] nhanh chóng đưa thuật toán O(n ) để giải toán sau: dem:=0; for j:=1 to n for i:=1 to j if s1[j]-s1[i-1]=s0[j]-s0[i-1] then inc(dem); Ở s1[k], s0[k] số lượng số 1, số lượng số đoạn [1,k] Hai mảng chuẩn bị trước thời gian O(n) Để cải tiến chương trình trên, sử dụng kỹ thuật hay dùng toán học phân li ẩn số: Nhận xét biểu thức s1[j]-s1[i-1]=s0[j]-s0[i-1] tương đương với s1[j]-s0[j]=s1[i-1]-s0[i1] (chuyển số hạng có j vế, số hạng có i về cịn lại) Ta đến kết luận quan trọng j cố định, biến dem tăng lượng số lượng vị trí i trước có s1[i]-s0[i]=s1[j]-s0[j] Sử dụng kỹ thuật mảng nhớ tốn có thuật tốn O(n): dem:=0; c[0]:=1; Bài toán 6: Cho dãy a1, a2, …, an Hãy tìm dãy tăng dài (các phần tử dãy tăng không thiết liên tiếp) dãy cho Nếu gọi f[i] độ dài dãy tăng dài kết thúc a[i] ta có cơng thức truy hồi sau: f [0] f [i] maxf [k] : k i, a[k] a[i]1 Ở a[0]=-vc số đủ nhỏ để cầm canh Nếu biết f[i] đáp số tốn max{f[i]: i=1,2,…,n} Để tính f[i], ,một thuật tốn O(n ) thường dùng sau: f[0]:=0; for i:=1 to n begin f[i]:=1; for k:=i-1 downto if (a[k]