Tài liệu bồi dưỡng học sinh giỏi Quốc gia.Cung cấp các kiến thức mà các học sinh muốn có giải quốc gia phải nắm được.Giúp các em học sinh chuẩn bị tốt cho những kì thi về lập trình.Tài liệu với lý thuyết và lời giải chi tiết.
Page of 84 MỤC LỤC Phương pháp duyệt Chuyên đề Duyệt vét cạn Chuyên đề Duyệt nhánh cạnh 12 Chuyên đề Duyệt ưu tiên 24 Tìm kiếm nhị phân Chuyên đề Tìm kiếm nhị phân ứng dụng 27 Xử lý bít Chuyên đề Xử lý bit 30 Quy hoạch động Chuyên đề Quy hoạch động 36 Chuyên đề Quy hoạch động trạng thái 49 Đồ thị Chuyên đề Tìm kiếm theo chiều rộng 58 Chuyên đề Tìm kiếm theo chiều sâu 69 Võ Văn Trị - CQB | Confidential PHƯƠNG PHÁP DUYỆT Chuyên đề Duyệt vét cạn - Backtracking Quay lui, vét cạn, thử sai, duyệt… số tên gọi không đồng nghĩa phương pháp tin học: tìm nghiệm toán cách xem xét tất phương án Đối với người phương pháp thường không khả thi số phương án cần kiểm tra lớn Tuy nhiên máy tính, nhờ tốc độ xử lý nhanh, máy tính giải nhiều toán phương pháp quay lui vét cạn Người đề chiến lược nhà toán học người Mỹ Derrick Henry Lehmer (1905 – 1991) vào năm 1950 Ưu điểm phương pháp quay lui, vét cạn bảo đảm tìm nghiệm đúng, xác Tuy nhiên, hạn chế phương pháp thời gian thực thi lâu, độ phức tạp lớn Về chất, tư tưởng phương pháp thử khả tìm thấy lời giải Đó trình tìm kiếm theo độ sâu tập lời giải Trong trình tìm kiếm, gặp hướng lựa chọn không thỏa mãn, ta quay lui, điểm lựa chọn có hướng khác thử hướng lựa chọn Khi thử hết tất hướng lựa chọn xuất phát từ điểm, ta quay lại điểm lựa chọn kế trước Quá trình tìm kiếm kết thúc không hư ớng lựa chọn để thử Chiến lược quay lui tương tự với tìm kiếm theo độ sâu tốn không gian nhớ hơn, thời gian tìm kiếm lại nhanh Mô hình thuật toán Backtracking: procedure try(i:integer); begin for begin ; if then else begin ; ; {th bước tiếp theo} ; end; end; end; Bài tập 1: Liệt kê tất dãy nhị phân có độ dài n Võ Văn Trị - CQB | Confidential Page of 84 Phân tích: Dãy nhị phân có độ dài n có dạng (x1, x2, …, xn) với xi ∈ {0, 1}, ≤ ≤ Như vậy, bước thứ i, ta tìm cách chọn giá trị cho biến x i {Chuong trinh cai dat thuat toan de quy} {Liet ke tat ca cac cau hinh nhi phan co dai n} Program BackTracking_ListsOfBinaryPermutations; Const n=3; var i,k:byte; h:array[1 20] of byte; Procedure Try(i:byte); var j:byte; begin for j:=0 to begin h[i]:=j; if i=n then begin for k:=1 to n write(h[k]); writeln; end else Try(i+1); end; end; begin try(1); end Bài tập 2: Liệt kê tất hoán vị tập {1, 2, …, n} Phân tích: Các hoán vị tập {1, 2, …, n} có dạng (x1, x2, …, xn) với xi ∈ {1, 2, … , }, ≤ ≤ xi # xj với i, j - Như vậy, việc xây dựng hoán vị thực qua n bước - Bước thứ i ta chọn số tập {1, 2, …, n} để đặt vào vị trí thứ i hoán vị - Tuy nhiên, ta chọn số x i chưa chọn cho vị trí KT trước Ta sử dụng mảng đánh dấu sau: False True True … Với ý nghĩa: - KT[i] = True i chưa chọn … … Võ Văn Trị - CQB | Confidential … n - KT[i] = False i chọn {Chuong trinh cai dat thuat toan de quy} {Liet ke tat ca cac hoan vi cua tap (1,2, ,n)} Program BackTracking_PermutationLists; Uses crt; Const n=3; var i,k:byte; kt:array[1 20] of boolean; h:array[1 20] of byte; Procedure Try(i:byte); var j:byte; begin for j:=1 to n if kt[j] then begin h[i]:=j; kt[j]:=false; if i=n then begin for k:=1 to n write(h[k],' '); writeln; end else Try(i+1); kt[j]:=true; end; end; begin clrscr; fillchar(kt[1],n,true); try(1); end Bài tập 3: Tổ hợp Một tổ hợp chập k n tập k phần tử n phần tử Chẳng hạn tập {1, 2, 3, 4} có tổ hợp chập là: {1, 2}, {1, 3}, {1, 4}, {2, 3}, {2, 4}, {3, 4} Vì tập hợp phần tử không phân biệt thứ tự nên tập {1, 2} tập hợp {2, 1}, ta coi chúng tổ hợp Yêu cầu: Hãy xác định tất tổ hợp chập k tập n phần tử Phân tích: Võ Văn Trị - CQB | Confidential Page of 84 Mỗi tổ hợp chập k n phần tử có dạng (x 1, x2, …, xk) đó: xi giá trị nằm tập {1, 2, …, n} tập hợp không phân biệt thứ tự nên ta xếp phần tử theo thứ tự tăng dần, ràng buộc x i < xi+1 với giá trị i từ đến k -1 - ứng cử viên xi chọn từ tập giá trị {x i-1 + 1, , n – (k-i)} - nguyên tắc chọn giúp ta khỏi cần phải dánh dấu, việc chọn giá trị phần tử chọn trước nên không bị lặp lại Chương trình - {chuong trinh de quy quay lui} {liet ke tat ca cac to hop chap k cua tap n phan tu} program BackTracking_PermutationLists; const n=4; k=3; var h:array[1 20] of byte; i:byte; procedure ghinghiem; var j:byte; begin write('{'); for j:=1 to k write(h[j],' '); writeln('}'); end; procedure try(i:byte); var j:byte; begin for j:= h[i-1]+1 to n-(k-i) begin h[i]:=j; if i=k then ghinghiem else try(i+1); end; end; begin try(1); readln; end Bài tập 4: Chỉnh hợp lặp Chỉnh hợp lặp chập k n phần tử dãy gồm k thành phần, thành phần phần tử tập n phần tử, không yêu cầu thành phần khác có phân biệt thứ tự cấu hình Ví dụ, dãy nhị phân có độ dài chỉnh hợp lặp chập tập phần tử {0, 1} Các dãy nhị phân có độ dài 3: 000, 001, 010, 011, 100, 101, 111 Võ Văn Trị - CQB | Confidential Vì có phân biệt thứ tự nên cấu hình 001 khác với 010 Như vậy, cách tìm nghiệm toán chỉnh hợp lặp sau: - Mỗi chỉnh hợp lặp chập k tập n phần tử có dạng (x 1, x2, …, xk) xi giá trị lấy tập {1, 2, …, n} ràng buộc thành phần {chuong trinh de quy quay lui} {liet ke tat ca cac chinh hop lap chap k cua n} program Backtracking_chinhhoplap; const n=2; k=3; var h:array[1 20] of byte; i:byte; procedure ghinghiem; var j:byte; begin for j:=1 to k write(h[j],' '); writeln end; procedure chinhhoplap(i:byte); var j:byte; begin for j:=1 to n begin h[i]:=j; if i=k then ghinghiem else chinhhoplap(i+1); end; end; begin chinhhoplap(1); readln end Bài tập 5: Chỉnh hợp không lặp Đối với chỉnh hợp lặp, thành phần phép lặp lại Đối với chỉnh hợp không lặp chập k n phần tử, thành phần không phép lặp lại Ví dụ, có n người, cách chọn k người để xếp thành hàng chỉnh hợp không lặp chập k n phần tử Một trường hợp đặc biệt chỉnh hợp k hông lặp hoán vị Hoán vị tập n phần tử chỉnh hợp không lặp chập n n Như vậy, cách tìm nghiệm toán sau: - Mỗi nghiệm toán dãy gồm k thành phần (x 1, x2, …, xk) Võ Văn Trị - CQB | Confidential Page of 84 - Mỗi thành phần x i giá trị lấy tập {1, 2, …, n} - Các giá trị đôi khác nhau, để kiểm soát ràng buộc này, ta sử dụng mảng đánh dấu ok với ý nghĩa sau: Ok[j] = true có nghĩa j chọn Ok[j] = false không chọn được, chọn j cho vị trí trước * Chương trình s au: {Chuong trinh de quy quay lui liet ke tat ca cac chinh hop ko lap} program Backtracking_chinhhopkolap; const n=2; k=2; var ok:array[1 20] of boolean; h:array[1 20] of byte; i:byte; procedure ghinghiem; var j:byte; begin for j:=1 to k write(h[j],' '); writeln; end; procedure Chinhhopkolap(i:byte); var j:byte; begin for j:=1 to n if ok[j] then begin h[i]:=j; ok[j]:=false; if i=k then ghinghiem else chinhhopkolap(i+1); ok[j]:=true; end; end; begin fillchar(ok[1],n,true); chinhhopkolap(1); readln; end Bài tập 6: Bài toán xếp tám quân hậu Một bàn cờ quốc tế bảng hình vuông gồm hàng, cột Quân hậu quân cờ ăn quân hàng, cột hay đường chéo Hãy xếp tám quân hậu bàn cờ cho quân hậu ăn quân hậu Giải : Võ Văn Trị - CQB | Confidential - Theo toán, cột (j=1 8) bàn cờ đặt quân hậu Như với cột ta phải tìm dòng thứ i để đặt quân hậu vào Có phương án chọn dòng i: i=1, 2, …, Ta đặt quân hậu vào ô [i,j] khi: - - - Đường chéo song song với đường chéo qua ô [i,j] chưa có hậu Đường chéo song song với đường chéo phụ qua ô [i,j] chưa có hậu Khi đó, thủ tục try(j) thực nhiệm vụ chọn dòng thứ i để đặt quân hậu thứ j vào ô [i,j] Ta minh họa bàn cờ sau: Nhìn vào bàn cờ, ta thấy: - - Dòng i chưa có hậu Các ô nằm đường chéo // với đường chéo hiệu số dòng số cột không đổi; Các ô nằm đường chéo // với đường chéo phụ tổng số cột số dòng không đổi; Vì thế, ta đánh dấu trạng thái bàn cờ sau: - Đánh dấu trạng thái dòng - Đánh dấu trạng thái đường chéo // với đường chéo Võ Văn Trị - CQB | Confidential Page of 84 - - Đánh dấu trạng thái đường chéo // với đường chéo phụ Để lưu giữ kết quả, ta sử dụng mảng chiều x {Chuong trinh de quy quay lui liet ke moi nghiem cua bai toan quan hau} program eightQueen; const fo='equeen.out'; var {danh dau trang thai dong} a:array[1 8] of boolean; {danh dau trang thai duong cheo // cheo chinh} b:array[-7 7] of boolean; {danh dau trang thai duong cheo // cheo phu} c:array[2 16] of boolean; x:array[1 8] of byte; j:byte; f:text; procedure ghinghiem; var i:byte; begin for i:=1 to write(f,x[i], ' '); writeln(f); end; procedure equeen(j:byte); var i:byte; begin for i:=1 to if a[i] and b[i-j] and c[i+j] then Võ Văn Trị - CQB | Confidential begin x[j]:=i; a[i]:=false; b[i-j]:=false; c[i+j]:=false; if j=8 then ghinghiem else equeen(j+1); a[i]:=true; b[i-j]:=true; c[i+j]:=true; end; end; begin fillchar(a[1],8,true); fillchar(b[-7],15,true); fillchar(c[2],15,true); assign(f,fo); rewrite(f); equeen(1); close(f); end Bài tập 7: Bài toán máy rút tiền tự động ATM Một máy ATM có n ( ≤ 20) tờ tiền có giá t 1, t2, …, tn Hãy đưa cách trả với số tiền s Input: tệp ATM.INP có dạng: - Dòng 1: ghi hai số n S; Dòng 2: ghi n số t1, t2, …, tn Output: ghi tệp ATM.OUT có dạng: Nếu trả S đưa cách trả, không ghi -1 ATM.INP 10 390 200 10 20 50 100 100 20 20 50 50 20 ATM.OUT 50 50 100 100 50 Nghiệm toán dãy nhị phân độ dài n, thành phần thứ i tờ tiền thứ i sử dụng, trường hợp ngược lại (x 1, x2, …, xn) nghiệm 1 + 2 + ⋯ + * Chương trình: {Chuong trinh de quy quay lui giai bai toan may rut tien tu dong ATM} Program AtmSolution; const fi='atm.inp'; Võ Văn Trị - CQB | Confidential Cho hai từ x, y dãy hữu hạn từ (w 1, w2, , wk) Phép toán p * q mang ý nghĩa phép nối từ p với từ q, hay nói cách khác p * q từ tạo thành cách viết từ q phía sau từ p Ta cần kiểm tra xem hai từ x, y tương đương hóa cách sử dụng từ dãy cho trước không Ví dụ: Từ abba ab tương đương hóa cách sử dụng từ dãy: baaabad aa badccaa cc Ta cần nối vào từ abba từ: aa badccaa, nối vào từ ab từ baaabad, cc aa theo thứ tự Trong hai trường hợp, ta thu từ: abbaaabadccaa Yêu cầu Cho biết từ x, từ y dãy từ w 1, w2, , wk Cho biết từ x y tương đương hóa cách sử dụng từ dãy cho trước hay không? Nếu có thể, tìm số lượng nhỏ phép toán * cần sử dụng Dữ liệu Dòng chứa số nguyên dương k ≤ 40 Dòng thứ hai dòng thứ ba mô tả từ x y K dòng mô tả dãy từ w1, w2, , wk, từ dòng Mô tả từ chứa số nguyên cho biết độ dài từ, theo sau khoảng trắng chuỗi thể từ Mỗi từ bao gồm chữ Latin in thường có độ dài không vượt 2000 Tổng độ dài từ không vượt 5000 Kết Nếu không tồn lời giải, in 'NIE' Nếu tồn lời giải, in số nguyên dương, số lượng nhỏ phép toán * cần để tương đương hóa hai từ x y Ví dụ VWORDS.INP 4 abba ab baaabad aa badccaa VWORDS.OUT Võ Văn Trị - CQB | Confidential Page 70 of 84 2 2 cc NIE a ab bb ab ba aa 8.6 GUMBI - Mã bài: LEM2 Một TV có N phím bấm đánh số N Trước TV tốt, ấn phím xuống phím khác tắt có phím vừa ấn bật Bây TV cũ, ấn phím,chỉ có số phím khác tắt(nếu bật), phím khác không đổi Một phím dù bật hay tắt ta ấn th ì phím bật Các phím bị tác động tắt bật Bạn cho biết kết bấm phím trạng phím Hãy tìm dãy bấm liên tiếp số phím cho cuối lại phím K, [...]... số: 233 3, 233 9, 239 3, 239 9, 2 939 , 31 19, 31 37, 37 33, 37 39, 37 93, 37 97, 5 939 , 71 93, 733 1, 733 3, 739 3 1 .3 Chèn phép toán (nguồn bài: Tài liệu giáo khoa chuyên tin Q1) Cho một xâu S chỉ gồm các ký tự từ ‘0’ đến ‘9’, độ dài nhỏ hơn 10 và số nguyên m, hãy đưa ra một cách chèn vào S các dấu ‘+’ hoặc ‘ -‘ để thu được số m cho trước (nếu có thể) Ví dụ, M=8, S = ‘1 234 56789’ thì một cách chèn là: ‘ -1+2 -3+ 4+5-6+7-8+9’... quá 32 000 Hãy xếp 8 quân hậu lên bàn cờ sao cho không có quân nào khống chế được quân nào và tổng các số ghi trên các ô mà quân hậu đứng là lớn nhất Input: tệp gồm 8 dòng, mỗi dòng ghi 8 số nguyên dương, giữa các số cách nhau một dấu cách Output: tệp có một số duy nhất là đáp số của bài toán 1 6 3 2 1 2 2 8 2 9 6 3 2 1 1 2 4 5 2 7 3 3 3 3 Dữ 9 3 4 2 3 4 3 2 2 3 4 2 2 8 4 2 liệu vào 2 1 4 3 1 4 1 8 3. .. dạng: - Dòng đầu là chi phí ít nhất; Dòng thứ hai mô tả hành trình Ví dụ 1 TSP.INP 4 0 20 35 42 20 0 34 30 35 34 0 12 42 30 12 0 TSP.OUT 97 1->2->4- >3- >1 Hình ảnh minh họa Ví dụ 2 Võ Văn Trị - CQB | Confidential Page 16 of 84 TSP.INP 4 0 20 35 10 20 0 90 50 35 90 0 12 10 50 12 0 TSP.OUT Hình ảnh minh họa 117 1->2->4- >3- >1 Giải 1) Hành trình cần tìm có dạng (x 1 = 1, x2, …, xn, xn+1 = 1), ở đây giữa x i... mỗi ô qua đúng 1 lần Ví dụ với n = 5: 1 24 13 18 20 15 4 11 14 9 3 19 2 10 8 23 21 7 25 12 16 5 6 17 22 1.2 Số siêu nguyên tố (nguồn bài: Tài liệu giáo khoa chuyên tin Q1) Số siêu nguyên tố là số nguyên tố mà khi bỏ bớt một số tùy ý các chữ số bên phải của nó thì phần còn lại vẫn là một số nguyên tố Ví dụ 233 3 là một số siêu nguyên tố có 4 chữ số vì 233 , 23, 2 cũng là các s ố nguyên tố Cho số nguyên... muốn chia K phần sao cho S lớn nhất Input - Dòng đầu là 2 số N,K(2 ≤ K ≤ N ≤ 200) N dòng tiếp theo mỗi dòng là N số a(i,j) (a(i,j) ≤ 32 767; n ếu i = j thì a(i,j) = 0) Output - Gồm 1 dòng duy nhất là S lớn nhất Example Input 4 3 0 1 2 1 0 2 2 2 0 3 3 3 Output 2 3 3 3 0 4 Mountain Walking - Mã bài: MTWALK Cho một bản đồ kích thước NxN (2