Những nhận xét bất ngờ khi giải một bài toán tin

5 1K 3
Những nhận xét bất ngờ khi giải một bài toán tin

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

Thông tin tài liệu

Những nhận xét bất ngờ khi giải một bài toán tin

Những nhận xét bất ngờ khi giải một bài toán tinNguyễn Xuân HuyNgười Pháp rất tự hào với ngôn ngữ của mình. Họ nhất quyết không chịu mượn thuật ngữ Computer theo tiếng Anh để nói về máy tính. Họ gọi máy tính là Ordinateur (đọc là or-đi-na-tơ). Từ này có nghĩa là người tổ chức trật tự. Càng ngẫm càng thấy người Pháp có lý. Hầu hết các vấn đề của tin học đều được giải quyết trên cơ sở xây dựng một quy trình? một trật tự xử lý. Trật tự đó có thể là dãy dữ liệu được sắp tăng hoặc giảm, trật tự xử lý các đỉnh hoặc cạnh trong đồ thị, thí dụ như ưu tiên theo chiều rộng hoặc chiều sâu, hoặc một trật tự xử lý mang lại kết quả tối ưu trong các bài toán tham lam. Để có được trật tự tối ưu chúng ta cần quan sát và phân tích chu đáo để đưa ra những nhận xét về tính chất của các đối tượng và quan hệ giữa các đối tượng cần xử lý. Đôi khi ta phát hiện ra những nhận xét hết sức bất ngờ và thú vị. Dưới đây là một số nhận xét tác giả thu lượm được từ các bạn học sinh phổ thông. Xin chia sẻ với bạn đọc. Bài 1 - Độ cao. Độ cao của một số tự nhiên là tổng các chữ số của số đó. Cho trước hai giá trị n và h. ký hiệu S(h,n) là số lượng các số tự nhiên độ cao h và có không quá n chữ số. Thí dụ, S(2,3) = 6 với các số 2, 11, 020, 101, 110, 200. Phân tích: Ta thấy S là hàm 2 biến. Trước hết hãy cho h và n các giá trị cận dưới. Ta thấy, Nhận xét 1: S(0, n) = 1, nếu n > 0; S(h,0) = 0. Nhận xét 2: Độ cao tối đa của số n chữ số là 9*n, do đó ta đặt S(h,n)=0 nếu h > 9*n. Nhận xét 3: S( h,1) = 1 với 0 ≤ h ≤ 9. Nhận xét 4: Nếu 101 là số độ cao h = 2 thì 999-101 = 898 là số độ cao h = 27-2 = 25. Tổng quát hóa nhận xét này ta thu được công thức S(h,n) = S(9*n-h,n). Như vậy, theo thí dụ trên ta tính được S(25,3) = S(3*9-25,3) = S(2,3) = 6 với các số 997, 988, 979, 898, 889, 799 (bạn nhớ thêm 0 vào bên trái các số cho đủ n chữ số). Rõ ràng là tính S(2,3) sẽ dễ chịu hơn S(25,3). Vậy thì trước hết ta chỉnh lại giá trị của tham số h trong S(h,n) như sau: if h > 9*n div 2 then h := 9*n - h; Nhận xét 5: Để tính S( h,n) ta qui định bù các số 0 vào bên trái sao cho mọi số đều có đúng n chữ số và dĩ nhiên chúng có cùng độ cao h. Ta chia tập toàn thể các số đó thành 10 lớp không giao nhau căn cứ vào chữ số cuối cùng? chữ số thứ n, đó là chữ số hàng đơn vị. Gọi chữ số đó là i, ta thấy, tổng n-1 chữ số còn lại sẽ là h-i. Như vậy số lượng các số thuộc lớp i (có chữ số cuối cùng là i) sẽ là S(h-i,n-1). Dĩ nhiên S(h-i,n-1) sẽ có nghĩa khi h-i ≥ 0 và n-1 > 0. Ta thu được công thức sau: Vậy là chỉ cần dùng một mảng một chiều S[0 MN] xử lý theo n bước lặp: bước lặp thứ j sẽ tính cho các số có không quá j chữ số. Nên chọn MN = 9*9 = 81, đó là độ cao tối đại của số có 9 chữ số. Tại bước j ta cần tính, với mỗi k = h 1 giá trị S[k] là số lượng các số độ cao k có không quá j chữ số. Bạn đọc tự lý giải vì sao phải tính ngược các giá trị S [k]. Nguyên tắc chung để xác định trật tự xử lý là: không ghi vào nơi chưa xử lý. Bạn thấy giống y chang với nguyên tắc lau nhà: Không bước vào nơi đã lau. Hàm S(h,n) sẽ được triển khai như sau: if h > 9*n div 2 then h := 9*n - h; fillchar(S,sizeof(S),0); {Khởi trị cho các số có 1 chữ số} for i:=0 to 9 do S[i]:=1; for j:=2 to n do for k:=h downto 1 do for i:=1 to min(k,9) do S[k]:=S[k]+S[k-i]; Bài 2 - Số đẹp Số tự nhiên hệ đếm b có 2k chữ số được gọi là số đẹp loại (b,k,h) nếu tổng k chữ số đầu bằng tổng k chữ số cuối và bằng h. Với ba giá trị b, k và h cho trước hãy cho biết có bao nhiêu số đẹp loại (b,k,h). Thí dụ, [1][0 ][19][0 ][0][20 ] là một số đẹp loại (25,3,20), trong đó mỗi chữ số * của hệ đếm 25 được ghi trong cặp ngoặc: [*]. Gợi ý: Mỗi số đẹp loại ( b,k,h) được ghép bởi 2 số x và y, trong đó x là số độ cao h có đúng k chữ số, y là số độ cao h có không quá k chữ số (nếu cần ta thêm 0 ở đầu trái số y). Hãy thực hiện đoạn trình trên một lần duy nhất để thu được ngay kết quả. Bài 3 - Chia đoạn (Đề thi Tin học Quốc gia Bulgary 2004) Cho hai dãy số nguyên dương a[1 n] và b[1 m]. Hãy chia mỗi dãy thành k đoạn, ký hiệu lần lượt từ trái qua phải là 1, 2, ., k, mỗi đoạn phải chứa ít nhất một phần tử của dãy tương ứng. Với mỗi đoạn i = 1, 2, ., k mso-ansi-language: VI'>hãy tính hàm C(i) = (t(a,i) ? s( a,i))*(t(b,i)-s(b,i)) Trong đó t(a,i) là tổng các phần tử của dãy a trong đoạn i, s(a,i) là số lượng phần tử của dãy a trong đoạn i, t(b,i) là tổng các phần tử của dãy b trong đoạn i, s(b,i) là số lượng phần tử của dãy b trong đoạn i. Cuối cùng ta tính trị Hãy cho biết giá trị nhỏ nhất của C? Thí dụ, với a = (1,2,3), b = (1,2), nếu chọn k =2 và chia hai dãy a và b như sau: a = ((1,2),(3)), b = ((1),(2)) thì C(1) = ((1+2)-2)*(1-1) = 1*0 = 0, C(2) = (3-1)*(2-1) = 2*1 = 2, C = C(1)+C(2) = 0+2 = 2. Phân tích: Nhận xét 1: Nếu giảm mỗi phần tử của hai dãy a và b đi 1 đơn vị thì công thức tính C(i) sẽ được rút gọn như sau: C(i) = t(a,i) *t( b,i) Bạn hãy tự giải thích điều này. Nhận xét 2: Kí hiệu F(i,j) là trị tối ưu của hàm C đối với hai dãy a[1 i] và b[1 j]. Ta xét đoạn cuối cùng, đoạn thứ k. Giả sử đoạn cuối cùng này chứa p1 phần tử của dãy a với tổng là s1 và p2 phần tử của dãy b với tổng là s2. Khi đó F(i,j) = min {F(i-p1,j-p2) + s1*s2} Cho i, j, p1 và p2 biến thiên ta tính đươc F. Tiếp cận này đòi hỏi độ phức tạp O(N4). Nhận xét 3: Với mọi đoạn k, p1 và p2 không thể đồng thời lớn hơn 1. Thật vậy, nếup1 > 1 và p2 > 1 thì ta có thể tách đoạn k thành hai đoạn con k1 và k2 với các tổng các phần tử lần lượt cho a và b là s1 = s11+s12 và s2 = s21+s22. Khi đó C(k) = s1*s2 = (s11+s12)*(s21+s22) = s11*s21 + s12*s22 + . ≥ s11*s21 + s12*s22 = C(k1)+C(k2). Theo nhận xét này, mỗi đoạn trong phép chia tối ưu chỉ có thể là một trong 3 dạng sau: i) chứa 1 phần tử của a và 1 phần tử của b, ii) chứa 1 phần tử của a và p2 > 1 phần tử của b, iii) chứa p1 > 1 phần tử của a và 1 phần tử của b, Vậy ta có F(i,j) = min {F(i-1,j-1) + a[i]*b[j], F(i-1,j-p2)+ a[i]*s2, F(i-p1,j-1)+ s1*b[j] } Nhận xét 4: Ta có a[i]*s2 = a[i]*(b[i-p2+1]+ .+b[j-1]+b[j]) = a[i]*(b[i-p2+1]+ .+b[j-1]) + a[i]*b[j], do đó, F(i-1,j-p2)+a[i]*s2 ≥ F(i,j-1) + a[i]*b[j]. Và tương tự, F(i-p1,j-1)+s1*b[j] ≥ F(i-1,j) + a[i]*b[j]. Vậy ta có, F(i,j) = min {F(i-1,j-1) + a[i]*b[j], F(i,j-1)+ a[i]*b[j], F(i-1,j)+ a[i]*b[j] } Đưa hạng tử amso-ansi-language: VI'>[i]*b[j] ra ngoài ta được một hệ thức thật đẹp và dễ tính vì chỉ cần độ phức tạp O(N2). F(i,j) = min {F(i-1,j-1), F(i,j-1), F(i-1,j)} + a[i]*b[j] Bạn thấy trật tự tính tóan đã giảm đáng kể độ phức tạp, từ bậc 4 xuống bậc 2. Gợi ý: Để tính hàm F theo công thức trên cần một mảng hai chiều. Liệu bạn có cách nào thay bằng hai mảng một chiều? Bài 4 - Số duy nhất (Đề thi Tin học các quốc gia Baltic, BOI 2004) Cho N số tự nhiên trong đó có duy nhất một số x xuất hiện đúng 1 lần, các số còn lại đều xuất hiện đúng K > 1 lần. Tìm số duy nhất x? Thí dụ, với 7 số 123, 123, 45, 123, 45, 405, 45 ta phải tìm được x = 405. Nhận xét 1: Nếu K là số chẵn thì ta dùng phép toán XOR bit N số đã cho, kết quả sẽ cho ngay số x cần tìm. Tuy nhiên bài toán không cho biết K là bao nhiêu. Nhận xét 2: Ta có thể tìm được số K bằng cách đếm số lần xuất hiện của số đầu tiên (kí hiệu là x) trong dãy. Nếu K=1 thì ta có ngay x là số cần tìm. Ngược lại, nếu K > 1 thì đó chính là số lần xuất hiện của các số còn lại. Vậy là yên tâm. Nhận xét 3: Với hai nhận xét đầu tiên chúng ta dễ bị tắc trong mê cung tìm kiếm. Hãy thử suy nghĩ về trật tự xem sao. Trật tự gì? Trật tự các số không cho ta thêm giải pháp nào. Ta thử tìm cách giải theo trật tự của các chữ số. Đúng vậy, từ hàng ngàn năm trước các nhà toán học cổ Hy Lạp như ácsimet và Ơclid đã nói rằng cùng là chữ số 1 nhưng nếu đặt ở vị trí khác nhau thì chữ số đó mang các giá trị khác nhau, khi thì là 1, khi là 10, khi là 100. Như vậy chúng ta phải đếm xem trong N số đã cho các chữ số trong từng hàng xuất hiện bao nhiêu lần. Ta dùng một mảng hai chiều a để ghi nhận các số đếm, a[c,j] cho biết số lần xuất hiện của chữ số c tại vị trí j. Ta thấy a[c,j] chỉ có thể chia hết cho K hoặc chia cho K dư 1. Bạn hãy giải thích điều này. Vì chỉ quan tâm đến các chữ số nên ta có thể đọc các dòng của tệp input vào các biến string. Ngoài ra ta cũng có thể xử lý các chữ số theo các vị trí tính từ phải qua trái. Ta giả thiết là số dài nhất trong dãy đã cho có MN=20 chữ số. MN = 20; var a: array['0' '9',1 MN] of word; x,y: string; c: char; N,K: word; f,g: text; 1. Mở các tệp inpyt f và output g. fillchar(a,sizeof(a),0); readln(f,N); readln(f,x); K:=1; for j:=1 to length(x) do inc(a[x[j],j]); for i:=2 to N do begin readln(f,y); if y=x then inc(K); for j:=1 to length(y) do inc(a[y[j],j]); end; if K > 1 then begin x:=''; for j:=1 to MN do for c:='0' to '9' do if a[c,j] mod K <> 0 then begin x:=x+c; break; end; end; writeln(g,x); close(f); close(g); Bài 5 - Dãy ký tự duy nhất Cho N xâu kí tự trên bảng chữ cái a z trong đó có duy nhất một xâu x xuất hiện đúng M lần, các xâu còn lại đều xuất hiện đúng K > M lần. Tìm xâu x? Bài sau đây các bạn chỉ nên giải vào chiều 30 tết. Bài 6 - Qua cầu (Tổng quát hóa đề thi tuyển nhân viên của hãng Microsoft) Một đàn con nít đi chơi đêm giao thừa với 1 chiếc đèn lồng. Gặp một cây cầu mỏng manh. Các em phải đưa nhau qua cầu. Cầu yếu, chỉ chịu được sức nặng của 2 em mỗi lượt, ngoài ra, cầu trơn và gập gềnh nên buộc phải soi đèn mới đi được. Mỗi em qua cầu với thời gian khác nhau. Hãy tìm cách để các em qua cầu nhanh nhất. Giả thiết cho n em với thời gian vượt cầu của mỗi em lần lượt là t1, t2,?,tn. Thí dụ, có 4 em với thời gian vượt cầu lần lượt là 1, 2, 5 và 10 phút. Theo phương án sau đây ta phải cần 19 phút: Cho em nhanh nhất? em số 1 cầm đèn dẫn tường người qua cầu: 1. Em 1 dẫn em 2: 2 ph.2. Em 1 cầm đèn về: 1 ph.3. Em 1 dẫn em 3: 5 ph.4. Em 1 cầm đèn về: 1 ph.5. Em 1 dẫn em 4: 10 ph. Nếu theo phương án sau đây ta được lời giải tối ưu: 17 ph. 1. Em 1 dẫn em 2: 2 ph.2. Em 1 cầm đèn về: 1 ph.3. Em 1 giao đèn cho em 3 và 4 qua cầu: 10 ph.4. Em 2 cầm đèn về: 2 ph.5. Em 1 dẫn em 2: 2 ph. Nhận xét 1: Một em quá chậm đi cùng em quá nhanh sẽ làm 'hạí em đi nhanh, do đó khi qua cầu nên cử hai em chậm nhất. Nhận xét 2: Khi cầm đèn chạy về nên giao cho em đi nhanh nhất. Chỉ với hai nhận xét trên chúng ta lập được trật tự giải bài toán trên như sau: Gọi nơi tập hợp các em nhỏ trước khi qua cầu là T (bên trái cầu), nơi cần đến là P (bên phải cầu). Trước hết tìm hai em đi nhanh nhất đòan là a và b. Lăp các bước 1-6 cho đến khi T rỗng: 1. a và b qua P,2. a cầm đèn về T,3. a giao đền cho 2 em chậm nhất x và y ở T,4. x và y qua P,5. x và y giao đèn cho b ở P,6. b trở về T. Bạn cần lưu ý trường hợp n=1. Ngoài ra mỗi khi đến P bạn cần kiểm tra ngay xem còn ai ở T không, mỗi khi ở T bạn lại phải kiểm tra xem còn bao nhiêu người chưa qua cầu, có như vậy vòng lặp mới kết thúc đúng lúc. . Những nhận xét bất ngờ khi giải một bài toán tinNguyễn Xuân HuyNgười Pháp rất tự hào với ngôn ngữ. ra những nhận xét về tính chất của các đối tượng và quan hệ giữa các đối tượng cần xử lý. Đôi khi ta phát hiện ra những nhận xét hết sức bất ngờ và thú

Ngày đăng: 11/09/2012, 08:55

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan