chuyendeduyencauhinhtohop

118
THPT CHUYÊN BẮC GIANG MỞ ĐẦU Duyệt các cấu hình tổ hợp và ứng dụng Trang 1

Upload: dat-luong-duc-tuan

Post on 04-Aug-2015

70 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

MỞ ĐẦU

Duyệt các cấu hình tổ hợp và ứng dụng Trang 1

Page 2: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

PHẦN 1. LÝ THUYẾT TỔ HỢP

I. SƠ LƯỢC VỀ TỔ HỢP

1. Khái niệm

Tổ hợp như là một lĩnh vực của toán học rời rạc, xuất hiện vào đầu thế kỉ 17.

Lý thuyết tổ hợp được áp dụng trong nhiều lĩnh vực khác nhau: lý thuyết số, hình học hữu hạn, biểu diễn nhóm, đại số không giao hoán, thống kê xác xuất, …

Lý thuyết tổ hợp gắn liền với việc nghiên cứu sự phân bố các phần tử vào các tập hợp. Các phần tử là hữu hạn và việc phân bố chúng phải thỏa mãn những điều kiện nào đó tùy theo yêu cầu của công việc (bài toán).

Mỗi cách phân bố như thế được gọi là một cấu hình tổ hợp (một bộ các phần tử nào đó).

2. Các bài toán thường gặp

a) Bài toán đếm: “Có bao nhiêu cấu hình thỏa mãn điều kiện đã nêu?”

Dùng để đánh giá hiệu quả công việc như: tính xác xuất của 1 sự kiện, độ phức tạp của một thuật toán.

b) Bài toán liệt kê: “Liệt kê tất cả các cấu hình tổ hợp có thể được” (các phương án)

Bài toán liệt kê làm nền, làm cơ sở cho nhiều bài toán khác.

c) Bài toán tối ưu: “Chỉ ra một hoặc một số cấu hình tốt nhất theo một nghĩa nào đó” (có giá lớn nhất hay có giá nhỏ nhất), là bài toán phổ biến trong cuộc sống

d) Bài toán tồn tại: “Có tồn tại hay không tồn tại cấu hình thỏa mãn điều kiện nào đó?”

Ví dụ về bài toán hình lục giác thần bí chẳng hạn

II. NHẮC LẠI LÝ THUYẾT TẬP HỢP

1. Các khái niệm và ký hiệu

– Tập hợp ký hiệu bằng chữ cái lớn A, B, … , X, Y, …

– Các phần tử ký hiệu bằng chữ cái nhỏ: a, b, x, y, …

– Nếu x là phần tử của tập X ta viết x X

– Nếu x không là phần tử của tập X ta viết x X

Duyệt các cấu hình tổ hợp và ứng dụng Trang 2

Page 3: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

– Tập A là tập con của tập B x A x B, kí hiệu A B

– Nếu đồng thời A B và B A thì A = B

– Số các phần tử của tập hợp A, ký hiệu là N(A) hoặc |A| (còn gọi là lực lượng của tập A)

– Một tập gồm n phần tử gọi là một n-tập

– Tập rỗng là tập không có phần tử nào, ký hiệu là

2. Các phép toán trên tập hợp

– Giao của 2 tập hợp A và B kí hiệu là A B: A B = {x | x A và x B}

– Hợp của 2 tập hợp A và B kí hiệu là A B: A B = {x | x A hoặc x B}

– Hiệu của 2 tập hợp A và B kí hiệu là A\B: A\B = {x | x A và x B}

– Phần bù của A trong X kí hiệu là : = {x |x X và x A}

– Tích đề các của 2 tập hợp A và B kí hiệu A x B hoặc A.B

– A x B = {(a, b)| a A và b B}

III. CÁC NGUYÊN LÝ CƠ BẢN

1. Nguyên lí cộng

Ví dụ 1: Có 8 quyển sách và 6 quyển vở khác nhau. Hỏi có bao nhiêu cách chọn 1 quyển trong các quyển trên?

* Hd:

Có 8 cách chọn ra 1 quyển sách

Có 6 cách chọn ra 1 quyển vở

Với mỗi cách chọn 1 quyển sách không trùng với cách chọn bất kì một quyển vở nào và ngược lại với mỗi cách chọn 1 quyển vở không trùng với cách chọn bất kì một quyển sách nào

=>có 8 + 6 = 14 cách chọn 1 quyển trong số các quyển sách và vở đã cho

* Đơn giản

Giả sử có m cách chọn đối tượng x, có n cách chọn đối tượng y và mỗi cách chọn đối tượng x không trùng với bất kỳ cách chọn đối tượng y nào và ngược lại mỗi cách chọn đối tượng y không trùng với bất kỳ cách chọn đối tượng x nào thì sẽ có m+n cách chọn 1 trong các đối tượng đã cho

* Nguyên lí cộng tổng quát

Duyệt các cấu hình tổ hợp và ứng dụng Trang 3

Page 4: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Nếu có m1 cách chọn đối tượng x1

Có m2 cách chọn đối tượng x2

…………

Có mn cách chọn đối tượng xn

Và mỗi cách chọn đối tượng xi không trùng với bất kì cách chọn đối tượng x j nào nếu i <> j (i,j = 1,2, …,n)

Thì có m1 + m2 +…+ mn cách chọn 1 trong các đối tượng đã cho

Ví dụ 2: Cho 2 tập hợp A và B, biết |A| = m và |B| = n và AB= . Hỏi |AB|=?

Ví dụ 3: Sau khi thực hiện xong các câu lệnh sau, giá trị của K bằng bao nhiêu?

n1 := 10; n2 := 20; n3 := 30;

k:=0;

for i1:=1 to n1 do k := k+1;

for i2:=1 to n2 do k := k+1;

for i3:=1 to n3 do k := k+1;

Ví dụ 4: Từ các chữ số 1, 2, 3 có thể lập được bao nhiêu số khác nhau, các chữ số trong mỗi số khác nhau?

* Hd VD4: Vì các số trong một số hạng là khác nhau nên số cần lập từ các số 1, 2, 3 chỉ có thể là số có 1 chữ số, có 2 chữ số, có 3 chữ số.

Gọi x1 là số cách chọn số có 1 chữ số

x2 là số cách chọn số có 2 chữ số

x3 là số cách chọn số có 3 chữ số

x1 = 3 (các số 1, 2, 3)

x2 = 6 (các số 12, 13, 21, 23,31, 32)

x3 = 6 (các số 123, 132, 213, 231, 321,312)

và với mỗi cách chọn số có 1 chữ số không trùng với cách chọn số có 2 chữ số và 3 chữ số và ngược lại

Theo nguyên lí cộng có 3+6+6 = 15 số khác nhau thỏa mãn đầu bài

2. Nguyên lí nhân

Ví dụ 5: Để đi từ TP A đến TP B có 3 cách chọn phương tiện đi lại (ôtô, tàu hỏa, máy bay), để đi từ TP B đến TP C có 4 cách chọn phương tiện đi lại (ôtô, tàu hỏa, tàu

Duyệt các cấu hình tổ hợp và ứng dụng Trang 4

Page 5: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

thủy, máy bay). Hỏi có bao nhiêu cách chọn bộ phương tiện để đi từ TP A đến TP C phải đi qua TP B?

* Hd:

Gọi x1 là phương tiện đi từ A đến B, x2 là phương tiện đi từ B đến C. Khi đó: Có 3 cách chọn đối tượng x1, với mỗi cách chọn đối tượng x1 có 4 cách chọn đối tượng x2

=>Số cách chọn bộ phương tiện để đi từ A B C đúng bằng số cách chọn bộ 2 thành phần (x1, x2)

= 3 x 4 = 12 cách

* Nguyên lí nhân tổng quát

Có m1 cách chọn đối tượng x1

với mỗi cách chọn đối tượng x1, có m2 cách chọn đối tượng x2

với mỗi cách chọn bộ đối tượng (x1, x2), có m3 cách chọn đối tượng x3

…..

với mỗi cách chọn bộ đối tượng (x1, x2,…, xn-1), có mn cách chọn đối tượng xn

=> thì có m1 x m2 x m3 x … x mn cách chọn 1 bộ có n thành phần (x1,x2…xn)

Ví dụ 6: Một lớp có 34 học sinh. Hỏi có bao nhiêu cách chọn ra một ban cán sự lớp gồm 1 lớp trưởng, 1 lớp phó, 1 bí thư.

Biết rằng mỗi học sinh được tham gia vào ban cán sự chỉ được nhận 1 nhiệm vụ và bất kì học sịnh nào cũng có thể tham gia ban cán sự?

GV đưa kq = 34 X 33 x 32 = 35904

Ví dụ 7: Có bao nhiêu số có 3 chữ số khác nhau lấy từ tập {0,1,2,3,4,5,6,7,8,9}?

GV đưa kq = 10 x 9 x 8 = 720

Ví dụ 8: Cho |A| = m và |B| = n chứng minh |AxB| = m*n

Ví dụ 9: Sau khi thực hiện xong các câu lệnh sau, giá trị của K bằng bao nhiêu?

n1 := 10; n2 := 20; n3 := 30;

k:=0;

for i1:=1 to n1 do k := k+1

for i2:=1 to n2 do k := k+1

for i3:=1 to n3 do k:=k+1;

Ví dụ 10: Có bao nhiêu xâu nhị phân độ dài 8?

Ví dụ 11: Có bao nhiêu xâu nhị phân độ dài n?

Duyệt các cấu hình tổ hợp và ứng dụng Trang 5

Page 6: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

GV đưa kq= 2n

Ví dụ 12: Có bao nhiêu tập con của một tập hợp có n phần tử A={a1, a2, .., an}?

* Hd ví dụ 12:

Xét xâu nhị phân có n bít x1,x2, … ,xn

Sự tương ứng 1-1 giữa 1 tập con của tập hợp A với 1 dãy nhị phân độ dài n.

Bởi vì:

nếu bít xi = 1 tương ứng với việc có mặt phần tử ai trong tập con

nếu bít xi = 0 tương ứng với việc không có mặt phần tử ai trong tập con

Do đó, số tập con của một tập hợp có n phần tử đúng bằng số xâu nhị phân độ dài n = 2n

3. Nguyên lí bù trừ

Nếu một nhiệm vụ có 2 công việc, 2 công việc có thể thực hiện đồng thời

Thì số cách thực hiện nhiệm vụ gồm 2 công việc đó bằng tổng số cách làm mỗi công việc trừ đi số cách làm đồng thời cả 2 công việc.

Ví dụ 13: |A| = m và |B| = n

|A+B| = m + n - |A B|

Ví dụ 14: Có bao nhiêu xâu nhị phân độ dài 8 thỏa mãn có bít đầu bằng 1 hoặc có 2 bít cuối là 00?

* Hd ví dụ 14:

+ Xâu nhị phân độ dài 8 có bít đầu bằng 1 là 1 bộ có dạng: 1x2x3x4x5x6x7x8, với xi=(0,1) ==> có 27 = 128 xâu thỏa mãn

+ Xâu nhị phân độ dài 8 có bít kết thúc bằng 00 là 1 bộ có dạng: x 1x2x3x4x5x600 => có 26 = 62 xâu thỏa mãn

+ Xâu nhị phân độ dài 8 có bít vừa bắt đầu bằng 1, vừa kết thúc bằng 00 là 1 bộ có dạng: 1x2x3x4x5x600, ==> có 25 = 32 xâu thỏa mãn

Vậy số xâu thỏa mãn đề bài là 128 + 64 – 32 = 160.

* Trường hợp đơn giản: Cho 2 tập hợp A và B (chưa biết có rời nhau hay không).

Khi đó: N(A B) = N(A) + N(B) - N(A B)

* Trường hợp tổng quát: Cho m tập hữu hạn A1, A2, ..,Am. Khi đó:

N(A1A2A3...Am) = N1-N2+N3-....+(-1)m-1Nm

Duyệt các cấu hình tổ hợp và ứng dụng Trang 6

Page 7: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Trong đó Nk là tổng phần tử của tất cả các giao của k_tập (tập con k phần tử) lấy từ m-tập đã cho, với k=2,3,4, ..., m-1

Đặc biệt:

N1 = N(A1) + N(A2) + ...+ N(Am)

Nm = N(A1A2 ...Am)

Ví dụ 17: Cho 3 tập hợp A, B, C. biết:

A = {0,1,2,7,11,14,25}

B = {-5,-4,0,2,7,13,15,16,19}

C = {-5,-2,2,7,13,14,16,20,21}

Hỏi N(A B C) = ?

* Hd: Ta có N(A) = 7; N(B)=9; N(C)=9;

N1=7+9+9 =25

N2=N(AB)+N(AC)+N(BC) = 3 + 3+5=11

N3 = N(ABC) = 2

Theo nguyên lí bù trừ ta có:

N(A B C)=N1-N2+N3 = 25-11+2=16

Ví dụ 18: Hỏi trong tập X={1,2,...,10000} có bao nhiêu số không chia hết cho bất cứ số nào trong các số 3,4,7?

* Bài tập tham khảo

BT1: Từ các số 0, 1, 2, .., 6 lập được bao nhiêu số tự nhiên chẵn có 3 chữ số?

BT2: Có bao nhiêu số có 2 chữ số mà chữ số hang chục khác 0 và số chẵn?

Bt3: Có bao nhiêu số tự nhiên có 5 chữ số trong đó số cách đều 2 số ở giữa là giống nhau? (vd 32123)

BT4: Có bao nhiêu số tự nhiên có 6 chữ số chia hết cho 5?

4. Nguyên lí Dirichlê

“Cần nhốt 6 thỏ vào 5 lồng thì ắt phải có 1 lồng chứa ít nhất 2 thỏ”

* TQ: “Có n đồ vật được đặt vào k hộp, ắt phải có ít nhất 1 hộp chứa ít nhất [n / k] đồ vật”

Ví dụ 15: Có 100 người. Hãy tìm xem có ít nhất bao nhiêu người có cùng tháng sinh?

TL: [100/12] = 9

Duyệt các cấu hình tổ hợp và ứng dụng Trang 7

Page 8: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Ví dụ 16: Trong số 367 người, có bao nhiêu người có cùng ngày sinh?

Tl: 1

IV. MỘT SỐ CẤU HÌNH TỔ HỢP THƯỜNG GẶP

1. Hoán vị

a. Định nghĩa: Một hoán vị của n phần tử (n >= 1) là một cách sắp thứ tự n phần tử đó.

Ví dụ1: Cho n=3 và các phần tử là {1,2,3} thì các hoán vị của 3 phần tử trên là: (1,2,3), (1,3,2), (2,1,3), (2,3,1), (3,1,2), (3,2,1)

Ví dụ 2: Có 5 người xếp hàng, có chiều cao bằng nhau. Hỏi có bao nhiêu cách xếp 5 người đó thành hàng?

*Tổng quát: Cho tập hợp A có n phần tử a1, a2, …,an. Một hoán vị của n phần tử của tập hợp A là một bộ có n thành phần (x1, x2, …,xn), xi A và xi <>xj i,j=1,2,..,n, i<> j

b. Số hoán vị của n phần tử kí hiệu là Pn

Ta có: Pn = n! = 1.2.3. … .n

*Chứng minh: Pn = n!

GV yêu cầu HS chứng minh

Gợi ý: Số hoán vị của n phần tử đúng bằng số bộ (x1, x2, …,xn), xi A và xi<>xj

với i <> j; ( i,j=1,2,..,n)

2. Chỉnh hợp lặp chập k của n phần tử

a. Định nghĩa: Một chỉnh hợp lặp chập k của n phần tử là một bộ có thứ tự gồm k thành phần lấy từ n phần tử đã cho, các thành phần có thể được lặp lại. (n>1, k>0)

Ví dụ 3: n=3, A = {1,2,3}. => các chỉnh hợp lặp chập 2 của 3 phần tử trên: (1,1), (1,2), (1,3), (2,1), (2,2), (2,3), (3,1), (3,2), (3,3)

*Tổng quát: Cho tập hợp A có n phần tử a1, a2…,an.

Một chỉnh hợp lặp chập k của n phần tử của tập hợp A là một bộ gồm k thành phần (x1, x2, …,xk), xi A, i=1,2,..,k

b. Số chỉnh hợp lặp chập k của n phần tử kí hiệu là : = nk

*Chứng minh: = nk

Duyệt các cấu hình tổ hợp và ứng dụng Trang 8

Page 9: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

GV yêu cầu HS chứng minh dựa trên nguyên lý nhân

Ví dụ 4: Mã khóa số có 3 chữ số lấy từ tập có 10 phần tử ={0,1,2,3,4,5,6,7,8,9}. Hỏi có bao nhiêu trạng thái của mã số?

GV hướng dẫn HS:

Mã khóa số là bộ có 3 thành phần (x1,x2,x3), với xi A, i=1,2,3

Vậy mỗi trạng thái của mã số là một chỉnh hợp lặp chập 3 của 10 phần tử của tập hợp A. => số trạng thái của mã số bằng số chỉnh hợp lặp chập 3 của 10 phần tử = = 103 = 1000

3. Chỉnh hợp không lặp chập k của n phần tử

a) Định nghĩa: Một chỉnh hợp không lặp chập k của n phần tử là một bộ có thứ tự gồm k thành phần khác nhau lấy từ n phần tử đã cho (n>1, k>0, n>k).

Ví dụ 5: n=3, A = {1,2,3}. => các chỉnh hợp không lặp chập 2 của 3 phần tử trên: (1,2), (1,3), (2,1), (2,3), (3,1), (3,2)

Ví dụ 6: Cho n=3, k=2 và A = {x, a, y}. => các chỉnh hợp không lặp chập 2 của 3 phần tử trên: (x,a), (x,y), (a,x), (a,y), (y,x), (y,a)

*Tổng quát: Cho tập hợp A có n phần tử a1, a2, …,an.

Một chỉnh hợp không lặp chập k của n phần tử của tập hợp A là một bộ gồm k thành phần (x1, x2, …,xk), xi A, i,j = 1,2, .., k và xi <> xj nếu i<>j

b)Số chỉnh hợp không lặp chập k của n phần tử kí hiệu là

= n.(n-1). ... .(n-k+1) =

*Chứng minh: =n.(n-1). ... .(n-k+1)=

GV yêu cầu HS chứng minh dựa trên nguyên lý nhân

4. Tổ hợp k của n phần tử

a) Định nghĩa: Một tổ hợp chập k của n phần tử là một bộ không kể thứ tự gồm k thành phần khác nhau lấy từ n phần tử đã cho, hai thành phần bất kì trong bộ đó phải khác nhau. (n>1, k>0, n>k)

Nói cách khác, một tổ hợp chập k của n phần tử là một tập con k phần tử của nó.

Ví dụ 7: Cho A = {1,2,3,4}. n=4, k=3. => các tổ hợp chập 3 của 4 phần tử là: (1,2,3), (1,2,4), (1,3,4), (2,3,4)

*Tổng quát: Cho tập hợp A có n phần tử a1, a2, …,an.

Duyệt các cấu hình tổ hợp và ứng dụng Trang 9

Page 10: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Một tổ hợp chập k của n phần tử của tập hợp A là một tập con gồm k thành phần (x1, x2, …,xk), xi A, i= 1,2, .., k và x1 < x2 < x3 < ... , xk

b)Số tổ hợp chập k của n phần tử kí hiệu là : =

Tư tưởng: Xây dựng số chỉnh hợp không lặp chập k của n phần tử bằng phương pháp phân hoạch.

B1: Từ tập n phần tử đã cho ta lấy ra tất cả các tập con k phần tử (x1,x2…xk)

==> Có cách chọn ra 1 tập con k phần tử từ tập n phần tử.

B2: Với mỗi tập con k phần tử, ta sắp thứ tự k phần tử của tập con đó ==> có k! cách sắp thứ tự.

Mỗi cách sắp thứ tự của k phần tử đó là một chỉnh hợp không lặp chập k của n phần tử đã cho.

=> theo nguyên lí nhân có = . k!

Thật vậy:

Trước tiên, ta xét tập các chỉnh hợp không lặp chập k của n phần tử.

Ta chia tập đó thành các lớp sao cho các chỉnh hợp không lặp chập k của n phần tử trong cùng một lớp giống nhau về các phần tử nhưng khác nhau ở thứ tự sắp xếp (Tức là, các chỉnh hợp không lặp chập k của n của 1 lớp là các hoán vị của cùng 1 tập con).

- Ví dụ: Tập các chỉnh hợp không lặp chập 3 của. 4 phần tử {1,2,3,4} được chia thành 4 lớp như sau:

Lớp 1: (1,2,3), (1,3,2), (2,1,3),(2,3,1),(3,1,2),(3,2,1)

Lớp 2: (1,2,4), (1,4,2), (2,1,4),(2,4,1),(4,1,2),(4,2,1)

Lớp 3: (1,3,4), (1,4,3),(3,1,4),(3,4,1),(4,1,3),(4,3,1)

Lớp 4: (2,3,4), (2,4,3),(3,2,4),(3,4,2),(4,2,3),(4,3,2)

- Ta nhận số lớp đúng bằng số tập con k phần tử của tập n phần tử đã cho (số tổ hợp chập k của n). Với mỗi lớp lại có k! chỉnh hợp không lặp chập k của n phần tử.

Nếu ta kí hiệu là số tổ hợp chập k của n thì theo nguyên lí nhân ta có:

= . k!, => = = (ĐPCM)

Ví dụ 8: Có n đội bóng thi đấu vòng tròn sao cho cứ 2 đội bất kì gặp nhau đúng một trận. Hỏi phải tổ chức bao nhiêu trận đấu?

* Hd ví dụ 8:

Duyệt các cấu hình tổ hợp và ứng dụng Trang 10

Page 11: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Cứ 2 đội thì có 1 trận đấu. Suy ra số trận đấu bằng số cách chọn 2 đội từ n đội,

bằng =

Ví dụ 9: Hỏi có bao nhiêu giao điểm của các đường chéo của một đa giác lồi n đỉnh (n > 4) nằm trong đa giác. Giả thiết rằng không có ba đường chéo nào đồng quy tại điểm ở trong đa giác.

* Hd ví dụ 9:

Cứ 4 đỉnh của đa giác, có một giao điểm của 2 đường chéo nằm trong đa giác.

Vậy số giao điểm của các đường chéo nằm trong đa giác đúng bằng số cách lấy ra 4 đỉnh từ tập n đỉnh của đa giác lồi đã cho.

=> Số giao điểm cần đếm là: = =

c) Một vài tính chất quan trọng của các hệ số tổ hợp

+ Tính đối xứng: =

+ Điều kiện đầu: = =1

+ Công thức đệ quy: = + với n.k>0

+ Tổng tất cả các tập con của tập n phần tử = 2n

+ Công thức nhị thức Niutơn

(x+y)n = xn + xn-1.y + ... + x.yn-1+ yn

Duyệt các cấu hình tổ hợp và ứng dụng Trang 11

Page 12: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

PHẦN 2. PHƯƠNG PHÁP SINH

I. Khái niệm

Phương pháp sinh được sử dụng trong bài toán liệt kê, ví dụ như người ta cần liệt kê tổ hợp chập k của n phần tử hay hoán vị của một tập số, hay khi người cần làm một bài toán mà không thể áp dụng các phương pháp thông minh như quy hoạch động, chia để trị thì phương pháp liệt kê để xét vét cạn là sự lựa chọn cuối cùng.Phương pháp sinh là phương pháp từ cấu hình đầu tiên ta sinh ra các cấu hình tiếp theo. Không phải bài nào cũng có thể làm theo phương pháp sinh, yêu cầu của bài toán để có thể làm theo phương pháp sinh là:

- Thứ nhất phải xác định được cấu hình đầu và cấu hình cuối

- Thứ hai phải xác định được cấu hình tiếp theo bằng 1 công thức nhất định

Việc xác định cấu hình đầu tiên và cấu hình cuối cùng là do yêu cầu đặt ra của từng bài toán và do cách xác định của từng người lập trình.

Yêu cầu quan trọng hơn khi sử dụng phương pháp sinh là làm sao từ cấu hình đang có ta có thể đưa ra được cấu hình tiếp theo hoặc là khẳng định đó là cấu hình cuối cùng. Ta tạm gọi bài toán từ cấu hình ban đầu sinh ra cấu hình tiếp theo có thủ tục là sinh_kế_tiếp. Khi đó bài toán sử dụng phương pháp sinh được viết như sau:

Procedure Generate;

Begin

<Xây dựng cấu hình ban đầu>;

Stop := False;

While not Stop Do

Begin

<Đưa ra cấu hình đang có>;

sinh_kế_tiếp;

End;

End;

Trong thủ tục sinh_kế_tiếp, nếu cấu hình đang có là cuối cùng thì thủ tục này cần gán cho biến Stop giá trị True, ngược lại thủ tục này sẽ xây dựng cấu hình kế tiếp của cấu hình đang có trong thứ tự đã xác định.

Duyệt các cấu hình tổ hợp và ứng dụng Trang 12

Page 13: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

II. Áp dụng phương pháp sinh vào giải một số bài toán

1. Bài toán 1: Liệt kê tất cả các dãy nhị phân có độ dài N.

Bài toán có thể được phát biểu như sau: Cho N là một số nguyên dương, hãy chỉ ra tất cả các dãy b1, b2, …, bN với bi {0; 1}, (1 i N).

Ví dụ với N = 3 ta có các dãy đó là:

1. 0 0 0

2. 0 0 1

3. 0 1 0

4. 0 1 1

5. 1 0 0

6. 1 0 1

7. 1 1 0

8. 1 1 1

Phân tích bài toán: Ta có thể thấy ngay dãy đầu tiên là 0 0 0 …0 (dãy toàn số 0) và dãy cuối cùng là 1 1 1 … 1 (dãy toàn số 1).

Từ cấu hình đang có thì cấu hình tiếp theo được xây dựng bằng cách cộng thêm 1 (cộng nhị phân) nếu ta cách biểu diễn cấu hình là biểu diễn nhị phân của một số nguyên. Ví dụ từ cấu hình 0 1 0 (2) thì cấu hình tiếp theo là 0 1 1 (3).

Từ cấu hình đang có b1, b2, …, bN ta có thể xây dựng cấu hình tiếp theo với qui tắc sau

- Tìm i đầu tiên (theo thứ tự i = n, n-1, .. 1) thoã mãn bi = 0;

- Gán lại bi = 1 và bj = 0 với tất cả j > i. Dãy mới thu được sẽ là dãy cần tìm.

Ví dụ: Xét dãy nhị phân độ dài 10, b = 1001001111.

+ Ta tìm được i đầu tiên = 5.

+ Bây giờ ta gán b5 =1 và b6, b7, b8, b9, b10 = 0 Xâu nhị phân kế tiếp là 1001010000 (tương ứng với 1001001111 (591) + 1 = 1001010000 (592))

Thuật toán sinh kế tiếp cho bài toán này được diễn tả như sau:Procedure Next_Bit_String;Begin

i := n;while bi = 1 do

Beginbi := 0;i := i -1;

End;bi := 1;

End;Chương trình của bài toán:

Duyệt các cấu hình tổ hợp và ứng dụng Trang 13

Page 14: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Program Bai1;var n, i: integer; b: Array[1..20] of 0..1; count : word; stop : boolean;Procedure init;var i: integer;Begin Write('Do dai day nhi phan = '); readln(n); for i := 1 to n do b[i] := 0; stop := false; count := 0;End;Procedure Next_Bit_String;Var i: integer;Begin i:=n; while (i>=1) and (b[i]=1) do Begin b[i] := 0; i := i-1; End; if i < 1 then stop := True Else b[i] := 1;End;BEGIN init; While not (stop) do Begin count := count + 1; Write(Count:5); For i := 1 to n do Write(b[i]:2); writeln; Next_Bit_String; End; Write('Bam phim Enter de thoat khoi Chuong trinh '); Readln;END.

2. Bài toán 2: Liệt kê các tập con m phần tử của tập n phần tử.

Bài toán có thể phát biểu như sau: Cho tập hợp Cho X = {1, 2, 3, .. , n}. Hãy liệt kê các tập con có m phần tử của X. Ví dụ: X= {1, 2, 3, 4, 5}, m= 3. Các tập con 3 phần tử của X là:

Duyệt các cấu hình tổ hợp và ứng dụng Trang 14

Page 15: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

1. {1, 2, 3} 2. {1, 2, 4} 3. {1, 2, 5} 4. {1, 3, 4} 5. {1, 3, 5}

6. {1, 4, 5} 7. {2, 3, 4} 8. {2, 3, 5} 9. {2, 4, 5} 10. {3, 4, 5}

Phân tích bài toán:

Mỗi tập con m phần tử của X có thể biểu diễn bởi bộ có thứ tự gồm m thành phần a = {a1, a2, .., am} thoả mãn 1 a1 < a2 < … am n.

Ta thấy cấu hình đầu tiên là {1, 2, 3, …, m} và cấu hình cuối cùng là {n-m+1, n-m+2, …, n}

Từ cấu hình đang có {a1, a2, .., am } ta tìm cấu hình tiếp theo bằng cách:

- Tìm từ bên phải dãy a1, a2, …, a3 phần tử ai n-m+i;

- Thay ai bởi ai+1;

- Thay aj bởi ai + j – i với j = i+1, i+2, …, m.

Ví dụ: Với n = 6 và m = 4. Giả sử tập con đang có là {1, 2, 5, 6}, cần xây dựng tập con kế tiếp.

+ Ta tìm được i = 2

+ Thay a2 = 3

+ Thay a3=4, a4= 5

ta được tập con kế tiếp là {1, 3, 4, 5}

Thuật toán sinh kế tiếp cho bài toàn này được diễn tả như sau:

Procedure Next_Combination;

Begin

i := m;

while ai = n – m + i do i := i - 1;

ai := ai + 1;

for j := i + 1 to n do aj := ai + j - i;

End;

Chương trình của bài toán được diễn tả như sau:

Program tap_con;

Var n, m,i : integer;

a: Array[1..20] of integer;

count: longint;

stop : boolean;

Duyệt các cấu hình tổ hợp và ứng dụng Trang 15

Page 16: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Procedure init;

Var i : integer;

Begin

Write('Moi nhap N '); Readln(n);

Write('Moi nhap M '); Readln(m);

For i:= 1 to m do a[i] := i;

stop := false;

count := 0;

End;

Procedure Next_Combination;

Var i, j: integer;

Begin

i := m;

while (i>0) and (a[i] = n-m+i) do i := i-1;

if i = 0 then stop := True

else

begin

a[i] := a[i]+1;

for j := i+1 to m do a[j] := a[i]+j-i;

end;

End;

BEGIN

init;

while not stop do

begin

count := count+1;

Write(count:5);

for i := 1 to m do write(a[i]:3); writeln;

Next_Combination;

end;

Duyệt các cấu hình tổ hợp và ứng dụng Trang 16

Page 17: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Write('Bam Enter de ket thuc '); Readln

End.

3. Bài toán 3: Liệt kê các hoán vị của tập n phần tử.

Bài toán có thể phát biểu như sau: Cho X = {1, 2, 3, .. , n}. Hãy liệt kê các hoán vị từ n phần tử của X. Ví dụ với n = 3 thì các hoán vị của nó là:

1. (1, 2, 3)

2. (1, 3, 2)

3. (2, 1, 3)

4. (2, 3, 1)

5. (3, 1, 2)

6. (3, 2, 1)

Phân tích bài toán:

Ta thấy ngay theo thứ tự trên thì cầu hình đầu tiên là: (1, 2, 3, . . n) và cấu hình cuối cùng là (n, n-1, ..., 2, 1).

Cần xây dựng thuật toán để từ cấu hình đang có là (a1, a2, …, an) ta tìm được cấu hình tiếp theo. Từ cấu hình đang có {a1, a2, …, an} ta xây dựng cấu hình tiếp theo bằng qui tắc:

– Tìm j đầu tiên thoả mãn aj<aj+1 (j giảm từ n, n-1, …, 1);

– Tìm ak là số nhỏ nhất và ak>aj trong các số aj+1, aj+2, …, an;

– Đỗi chỗ aj với ak;

– Đảo ngược đoạn từ aj+1 đến an.

Ví dụ với n = 6, cấu hình đang có là (3, 6, 2, 5, 4, 1)

+ Ta tìm được j = 3

+ Ta tìm được k = 5

+ Hoán vị a3 với a6 ta được (3, 6, 4, 5, 2, 1)

+ Đảo ngược đoạn a4, a5, a6 ta được (3, 6, 4, 1, 2, 5)

Cấu hình tiếp theo là (3, 6, 4, 1, 2, 5)

Chương trình của bài toán là:

Program hoan_vi;

Var a:array[1..100] of integer;

n,i: integer;

count: longint;

stop : Boolean;

Duyệt các cấu hình tổ hợp và ứng dụng Trang 17

Page 18: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Procedure init;

var i: integer;

Begin

Write('Moi nhap vao N '); Readln(n);

For i := 1 to N do a[i]:=i;

Stop := False;

Count := 0;

end;

Procedure next_Permution;

Var j,k,l,m:integer;

tg: integer;

Begin

j := n-1;

while (j >0) and (a[j] > a[j+1]) do dec(j);

if j = 0 then stop := True else

begin

k := n;

while a[j] > a[k] do dec(k);

tg := a[j];

a[j] := a[k];

a[k] := tg;

l := n;

m := j+1;

while l > m do

begin

tg := a[l];

a[l] := a[m];

a[m] := tg;

dec(l);

inc(m);

Duyệt các cấu hình tổ hợp và ứng dụng Trang 18

Page 19: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

end;

end;

end;

BEGIN

init;

while not stop do

begin

inc(count); write(count,'. ');

For i := 1 to N do write(a[i]:3); writeln;

next_permution;

end;

Write('Bam Enter de ket thuc '); Readln;

END.

4. Bài toán 4: Phân tích số nguyên dương N thành tổng các số nguyên không âm.

Bài toán được phát biểu như sau: Cho một số nguyên dương N. Hãy liệt kê các cách phân tích N thành tổng các số nguyên không âm. Ví dụ với N = 4, ta có thể phân tích thành:

1. 4

2. 3 + 1

3. 2 + 2

4. 2 + 1 + 1

5. 1 + 1 + 1 + 1

Phân tích bài toán:

Ta có thể thấy ngay cấu hình đầu tiên là: N và cấu hình cuối cùng là 1 1 1 … 1 (N chữ số 1).

Cần xây dựng thuật toán để từ cấu hình ta tìm được cấu hình tiếp theo. Từ cấu hình a1, a2, …, ak ta có thể xây dựng cấu hình tiếp theo với quy tắc sau:

- Tìm i đầu tiên sao cho ai 1 (i giảm từ k, k-1, … 1)

- Thay ai = ai -1

- Phân tích (k-i+1) thành các số như sư:

+ Gán aj :=ai với j từ i+1 đến i + [(i+ k-i+1) div ai ];

Duyệt các cấu hình tổ hợp và ứng dụng Trang 19

Page 20: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

+ Gán aj+1 := [(k-i+1) mod ai] nếu [(k-i+1) mod ai] 0

(Số phần tử được phân tích thành bây giờ là i + [(k-i+1) div ai] + [(k-i+1) mod ai]

Ví dụ: Với N=10

*Từ cấu hình 4 4 1 1 (k=4)

- Ta tìm được i = 2

- a2 := a2 - 1 (a2 = 3)

- ta có k-i+1 div a2 = 1 và k-i+1 mod a2 = 0 số phần tử tiếp theo là 1 đó là a3 = a2 (a3 = 3)

Cấu hình tiếp theo là: 4 3 3

*Từ cấu hình 4 3 3 (k=3)

- Ta tìm được i =3

- a3 := a3-1 (a3 = 2)

- Ta có k-i+1 div a3 = 0 và k-i+1 mod a2 = 1 số phần tử tiếp theo là 1 đó là a4 = 1

Cấu hình tiếp theo là: 4 3 2 1

Chương trình của bài toán là:Program phan_tich;Var c: array[1..1000] of integer;

k, n: integer; count: longint; Stop: Boolean;

Procedure init;Var i,j:integer;Begin

Write('Moi nhap so nguyen duong N '); Readln(N); k := 1; c[k] := n; Count := 0; Stop := False;

end;Procedure Result;Var i: integer;Begin

inc(count); Write(count,'. '); For i := 1 to k do write(c[i]:3);

Duyệt các cấu hình tổ hợp và ứng dụng Trang 20

Page 21: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

writeln;End;Procedure Next_Division;Var i, j, r, s, d : integer;Begin

i := k; while (i>0) and (c[i] =1) do dec(i); if i>0 then begin

c[i] := c[i]-1; d := k-i+1; r := d div c[i]; s := d mod c[i]; k := i; if r>0 then begin

for j := i+1 to i+R do c[j]:=c[i]; k := k+r;

end; if s>0 then begin

k := k+1; c[k] := s; end; end else stop := True;

End;Procedure Division;Var i: integer;Begin While not stop do

begin result;

next_division; end;

Write('Bam Enter de ket thuc '); ReadlnEnd;BEGIN

init; division;

END.

Duyệt các cấu hình tổ hợp và ứng dụng Trang 21

Page 22: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Như vậy, với mỗi bài toán như trên, khi sử dụng phương pháp sinh vào giải quyết chúng ta thường gặp khó khăn như sau: một là việc xác định cấu hình đầu tiên và cấu hình cuối cùng, hai là việc xác định được quy tắc để từ cấu hình đang có ta tìm ra được cấu hình tiếp theo (sinh ra cấu hình tiếp theo). Chính vì nguyên nhân đó mà phương pháp sinh không được sử dụng rộng rãi vào giải quyết các bài toán như thuật toán quay lui, quy hoạch động, …Phương pháp sinh chỉ được sử dụng vào giải quyết một số bài toán liệt kê các cấu hình tổ hợp đơn giản.

Duyệt các cấu hình tổ hợp và ứng dụng Trang 22

Page 23: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

PHẦN 3. GIẢI THUẬT QUAY LUI

1. Ý tưởng

Trước hết ta xét 2 ví dụ sau để tạm hiểu thế nào là quay lui.

Ví dụ 1: Liệt kê dãy hoán vị từ 1..n.

Xét trường hợp n=3 ta có cây liệt kê các hoán vị của n như sau:

Hình H1.

Gọi D là tập hợp các phần tử từ 1 đến n (n=3), trong tập hợp D=(1,2,3) lần lượt lấy các giá trị X(x1, x2, x3) để được một hoán vị.

Ví dụ: HV(1,2,3); HV(2,3,1); HV(1,3,2)...

Ban đầu trong D, các giá trị 1, 2 và 3 đều sẵn sàng.

– Bước 1, D(1,2,3) ta chọn x1=1, đánh dấu đã chọn 1 trong còn D(2,3).

– Bước 2, D(2,3) chọn x2=2, đánh dấu đã chọn 2 hay D(3).

– Bước 3, D(3) chọn x3=3, đánh dấu đã chọn 3 hay D().

Xét thấy dãy X thoả mãn là một hoán vị X=123 (chọn đủ n=3 giá trị x1, x2 và x3), ghi nhận hoán vị này. Tiếp tục tìm kiếm cách thay thế giá trị của các x i

(i=1..3) để được hoán vị khác.

Thông thường và để tránh trường hợp bỏ xót nghiệm ta thường bắt đầu xét lại theo quy luật nào đó. Trong bài toán này, ta bắt đầu từ x3 tr ở về trước. Chọn giá trị khác 3 trong D cho x3, giải phóng phóng 3. Xét thấy trong D không còn giá trị nào thoả mãn. Vậy ta phải xem xét lại từ x2 (tại Bước 2).

Duyệt các cấu hình tổ hợp và ứng dụng Trang 23

Page 24: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Tất nhiên, khi trở lại bước 2. Phần tử đang xét là x2, có nghĩa là x3 chưa nhận giá trị nào và x2 cũng không nhận lại giá trị 2 nữa vì đã nhận trước đó rồi (để tránh trùng nghiệm và mất thời gian)... Từ hình vẽ trong ví dụ này là ta trực tiệp nhìn thấy. Nhưng với số lượng các phần tử trong D nhiều và rất nhiều, đồng thời với máy tính không thể suy luận và nhìn thấy theo cách này mà phải dùng kĩ thuật đánh dấu thông qua các biến hoặc kĩ xảo lập trình để ghi nhận các giá trị đã hoặc chưa xét.

– (Bước 2.2)Tại đây ta chọn giá trị khác cho x2 trong D, chọn x2=3 thoả mãn.

– (Bước 2.3) Chọn một giá trị cho x3 trong D, được x3=2 thoả mãn.

Xét thấy dãy X thoả mãn là một hoán vị X=132, để tìm các hoán vị khác ta lại bắt đầu từ x3 ngược trở lại, tìm một giá trị trong D không lặp lại và chưa được chọn.

Lại tìm giá trị khác cho x3, không tìm thấy giá trị nào trong D thoả mãn, quay lại Bước 2.2 (Bước 2), tại đây cũng không tìm được giá trị nào thoả mãn cho x 2. Tiếp tục quay về bước trước đó là Bước 1 để xác định lại x1.

– (Bước 1.2) Ta chọn x1=2, trong còn D(1,3). Tiếp theo ta chọn x2=1, trong còn D(3) và cuối cùng chọn x3=3. Thoả mãn là một hoán vị X=213. Tiếp tục tìm các hoán vị khác, lại quay ngược trở lại cho đến khi tìm được giá trị thoả mãn cho xi nào đó.

– Cứ như vậy cho đến khi không còn quay lui được nữa. Thuật toán kết thúc và ta tìm xong các nghiệm của bài toán.

Ví dụ 2: Cho bàn cờ vua NxN, hãy tìm tất cả các cách đặt N quân hậu lên bàn cờ sao cho không quân nào ăn được quân nào.

H1-1

Một lời giả của bài toán khi n=4. Hình H1-1.

Ta nhận thấy rằng mỗi quân hậu sẽ được đặt trên một hàng, nên ta gọi quân hậu đặt ở hàng 1 là hậu 1, quân hậu đặt ở hàng 2 gọi là hậu 2… quân hậu ở hàng n gọi là quân hậu n. Vấn đề là tìm xem hậu i được đặt tại cột j nào (j=1..n) sao cho không hậu nào ăn được hậu nào.

* Hd:

– Đặt tất cả các hậu tại đầu mỗi hàng như hình H1-2, sau đó lần lượt đặt các quân hậu từ 1 đến n vào các cột tương ứng từ 1 đến n sao cho không hậu nào ăn được nhau.

Duyệt các cấu hình tổ hợp và ứng dụng Trang 24

Page 25: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

– Đặt hậu 1- vào ô 11, đặt hậu 2- vào ô 23 (ô 21 và 22 bị hậu 1 ăn được), tại dòng 3 các ô đều bị hậu 1 hoặc hậu 2 không chế, vậy đi theo cách này không được. quan sát hình ảnh sau:

H1-3

Các vị trí đánh dấu (X) bị hậu đặt trước đó khống chế

– Do vậy ta phải đặt lại hậu 2.

H1-4

dấu “chấm đậm” thể hiện vị trí đã được thử đặt trước đó

– Đặt hậu 2 vào ô 24, hậu 3 vào ô 32, -> không có cách đặt hậu 4, đi theo hướng này không có lời giải. Nên ta chọn lại cách đặt hậu 3, từ hình H1-4 thấy rằng không còn cách đặt khác cho hậu 3, nên ta quay lại và thử đạt lại hậu 2 một lần nữa, từ hình H1-4 thấy rằng không còn cách đặt hậu 2. Ta tiếp tục quay lại tìm cách đặt lại hậu 1. Còn với cách đặt hậu 1 tại ô 11 thì sẽ không tìm thấy lời giải. Bây giờ ta đặt hậu 1 sang ô 22 và tiếp tục với các hậu khác ta có kết quả như sau:

H1-5

– Từ bàn cờ cuối trong hình H1-5 ta thấy đây là một lời giải của bài toán, ghi nhận nghiệm này và tiếp tục tìm lời giải khác.

– Lần lượt đặt lại các vị trí của các hậu, bắt đầu từ hậu 4 quay dần trở lại.

– Xét hậu 4: còn ô 44 nhưng lại bị hậu 2 không chế, nên ta quay lại hậu 3.

– Xét hậu 3: các ô 32, 33 và 34 bị hậu 1 hoặc 2 không chế. Quay lại hậu 2.

– Xét hậu 2: hết ô có khả năng đặt hậu, quay lại hậu 1.

Duyệt các cấu hình tổ hợp và ứng dụng Trang 25

Page 26: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

– Xét hậu 1: đặt vào ô 13; hậu 2 đặt vào ô 21; ô 31, 32 và 33 không thoả mãn nên đặt hậu 3 vào ô 34 và cuối cùng đặt hậu 4 vào ô 42. Ta thu được nghiệm của bài toán, quan sát hình ảnh dưới đây:

Hình H1-6.

– Bằng cách thử lại tương tự để tìm lời giải khác cho bài toán. Xét hậu 4, hậu 3 và hậu 2 đều không tìm được ô khác. Trở lại từ hậu 1 đặt tại ô 14… (đi theo hướng này cũng không có lời giải - người đọc tự làm tiếp).

– Kết luận: với n=4 tồn tại hai nghiệm (2,4,1,3) và (3,1,4,2)

Tóm lại, từ các ví dụ trên cho ta thấy, nghiệm của bài toán có dạng X(x1,x2…xn) và để giải bài toán ta thường dựa vào hai điều kiện:

– Điều kiện 1(P) để xây dựng phần tử xi: ta lần lượt đưa ra các giá trị đề cử cho xi

và kiểm tra xem các giá trị này có thoả mãn hay không. Nếu được, tiếp tục với x i+1; nếu không, có nghĩa là đi theo hướng này không tìm được nghiệm. Ta phải quay lại và xét lại phần tử xi-1 với một giá trị đề cử khác. Hành động này gọi là quay lui.

– Điều kiện 2(Q) để kiểm tra xem các thành phần từ x1 đến xi đã là nghiệm của bài toán hay chưa. Nếu thoả mãn thì ghi nhận nghiệm và dừng chương trình hoặc lại lần lượt xét lại các xi, xi-1... để tìm nghiệm khác của bài toán.

2. Thuật toán quay lui

Nội dung chính của thuật toán này thường dùng để giả các bài toán liệt kê và tối ưu tổ hợp mà nghiệm của nó là một dãy các thành phần X=(x1…xn) được lấy ra từ một tập hợp dữ liệu cho trước D theo một thứ tự và điều kiện cụ thể.

Để xây dựng thuật toán này ta thực hiện theo ý tưởng sau: giả sử ta đang xét thành phần xi trong D xem có thoả mãn điều kiện P hay không, nếu thoả mãn thì ghép vào nghiệm sau đó xét tiếp thành phần xi+1, còn nếu không tìm thấy xi nào thảo mãn điều kiện (P hoặc Q), thì quay trở lại thành phần trước đó là x i-1, bỏ giá trị này đi và tại đây tìm một giá trị khác thoả mãn P cho xi-1. Sau đó lại tiếp tục tìm xi, xi+1… cho đến khi thoả mãn Q.

Viết lại ý tưởng theo như sau:

Bước 1: Xuất phát từ tập hợp D, ta tìm được các thành phần của nghiệm X=(x1…xi) được lấy trong D thoả P.

Duyệt các cấu hình tổ hợp và ứng dụng Trang 26

Page 27: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Bước 2: Nếu X thoả Q dừng thuật toán, thông báo tìm được nghiệm X. Nếu không thoả Q chuyển sang bước 3.

Bước 3: Xét tiết thành phần xi+1 để bổ sung cho X: (x1…xi+1) thoả P. Xảy ra trường hợp sau đây:

Tìm được xi+1, quay lại Bước 2.

Không, tức là với mọi xi+1 thì (x1…xi+1) không thoả P, có nghĩa là nghiệm X theo hướng (x1…xi) đã xét sẽ không đi đến kết quả, do vậy ta phải chọn một giá trị khác trong D cho xi để làm được điều này ta giảm i một đơn vị rồi quay về Bước 3.

Cách làm như trên gọi là quay lui một bước để tìm nghiệm của bài toán theo hướng khác. (thuật toán, giả thuật, tìm kiếm + quay lui hoặc backtracking).

Để đảm bảo cho việc vét cạn mọi khả năng có thể có, các giá trị đề cử không được bỏ sót. Để đảm bảo việc xét không bị trùng lặp, khi quay lui để xác định lại các xi cần không thử lại các giá trị đã thử rồi. Lúc này ta cần kết hợp kỹ thuật đánh dấu hợp lý các giá trị đã thử trước đó và khi quay lui ta cần trả về trạng thái cũ.

Từ ý tưởng trên ta đưa ra hai sơ đồ giải bài toán quay lui tìm nghiệm không đệ quy như sau:

Khởi tạo X, X thoả P

Repeat

If X thoả Q then

Begin

Ghi nhận nghiệm;

Exit;

[Lùi; tìm các nghiệm;]

End;

If Tìm một nước đi Then Tiến

Else Lùi;

Until False;

If không nghiệm Then

Else Begin

Ghi nhận vô nghiệm;

Exit;

End;

Khởi tạo X, X thoả P

Repeat

If X thoả Q then

Begin

Ghi nhận nghiệm;

Exit;

[Lùi; tìm các nghiệm;]

End;

If Tìm một nước đi Then Tiến

Else Lùi;

Until False;

If không nghiệm Then

Begin

Ghi nhận vô nghiệm;

Exit;

End;

Duyệt các cấu hình tổ hợp và ứng dụng Trang 27

Page 28: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

– Dưới đây là cách thể hiện dùng đệ quy tìm thành phần thứ i của nghiệm:

Duyệt các cấu hình tổ hợp và ứng dụng Trang 28

Page 29: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Procedure Try(i : Integer);{Xác định thành phần xi bằng đệ quy}Var j: Integer;Begin

For <j tập các khả năng đề cử> do

If <chấp nhận j> then

Begin<xác định xi theo j>;if i = n thenBegin

<ghi nhận nghiệm>;[exit; tìm nghiệm đầu tiên và thoát]

End

Else Begin

[ghi nhận trạng thái mới];Try(i+1);

[trả lại trạng thái cũ];

End;End;

End;

Trong chương trình chính chỉ cần lời gọi Try(1) để khởi động cơ cấu đệ quy hoạt động. Tất nhiên, trước đấy cần khởi tạo các giá trị ban đầu cho các biến. Thông thường việc này được thực hiện qua một thủ tục nào đấy mà ta gọi là Init.

Trong thủ tục Try(i: integer) ta xem xét kỹ các vấn đề sau:

– Tập các khả năng đề cử: Các giá trị đề cử thông thường lớn hơn số được chấp nhận. Sự chênh lệch này càng lớn thì thời gian phải thử càng nhiều, vì thế càng thu hẹp được diện đề cử càng nhiều càng tốt (nhưng không được bỏ sót !). Việc này phụ thuộc vào việc phân tích các điều kiện ràng buộc của cấu hình để phát hiện những điều kiện cần của cấu hình đang xây dựng. Lý tưởng nhất là các giá trị đề cử được mặc nhiên chấp nhận. Trong trường hợp này mệnh đề <chấp nhận j> được bỏ qua (vì thế cũng không cần các biến trạng thái).

Ví dụ: duyệt các chỉnh hợp lặp chập k của n giá trị 1,2,…,n. Mỗi chỉnh hợp được tổ chức như một mảng k thành phần:

x[1], x[2], … ,x[k]

Duyệt các cấu hình tổ hợp và ứng dụng Trang 29

Page 30: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

trong đó, mỗi x[i] có thể lấy một trong các giá trị từ 1 đến n. Theo định nghĩa chỉnh hợp lặp, các giá trị này là độc lập với nhau, vì thế việc đề cử bất kỳ giá trị nào từ 1 đến n cho x[i] đều mặc nhiên được chấp nhận. Các chỉnh hợp chập 3 (k=3) của 5 (n=5) giá trị 1,2,3,4,5 gồm nk = 53 =125 bộ nghiệm.

– Điều kiện chấp nhận : Điều kiện chấp nhận một giá trị đề cử được tính toán trong thân vòng lặp của thủ tục đệ quy Try, vì thế tiết kiệm được một phép toán trong biểu thức này là tiết kiệm được vô số các phép toán thực sự phải làm. Thông thường, điều kiện chấp nhận tính tại bước i phụ thuộc vào cả những bước trước, vì thế để tiết kiệm số phép toán, người ta thường dùng một số kỹ thuật sau:

Tổ chức những biến trạng thái để lưu trữ những thông tin cần thiết. Thay vì phải tính lại, ta có thể truy xuất các giá trị của những biến này. Việc dùng một số biến trạng thái, tuy phải trả giá bằng một số vùng nhớ nhất định nhưng tiết kiệm được nhiều thời gian tính. Việc tổ chức hợp lý các biến trạng thái cũng là một kỹ thuật làm tăng hiệu quả của việc duyệt.

Trong những tình huống phải tính lại, cố gắng kế thừa kết quả của những bước trước bằng cách tổ chức thêm những tham số cho thủ tục đệ quy Try để truyền cho những bước kế tiếp.

Nói chung, việc đưa ra được một biểu thức đơn giản để tính điều kiện chấp nhận được là kết quả của việc phân tích kỹ lưỡng bài toán cũng như tổ chức tốt dữ liệu. Mặt khác, điều kiện này được tính càng sát càng tốt, nó giúp ta lùi sớm hơn (tiết kiệm thời gian hơn) trong quá trình tìm kiếm.

– Ghi nhận trạng thái mới và trả lại trạng thái cũ: tuỳ theo từng bài cụ thể.

3. Các ví dụ

(Các chương trình trong phần này được viết trên môi trường Free Pascal)

a. Chỉnh hợp lặp

Phát biểu: Một chỉnh hợp lặp chập k của n phần tử là một bộ có thứ tự gồm k thành phần lấy từ n phần tử đã cho, các thành phần có thể được lặp lại. (n>1, k>0)

Vd: k=2, n=3. => các chỉnh hợp lặp chập 2 của 3 phần tử như sau: (1,1), (1,2), (1,3), (2,1), (2,2), (2,3), (3,1), (3,2), (3,3)

Nhắc lại: duyệt các chỉnh hợp lặp chập k của n giá trị 1,2,…,n. Mỗi chỉnh hợp được tổ chức như một mảng k thành phần:

x[1], x[2], … ,x[k]

trong đó, mỗi x[i] có thể lấy một trong các giá trị từ 1 đến n. Theo định nghĩa chỉnh hợp lặp, các giá trị này là độc lập với nhau, vì thế việc đề cử bất kỳ giá trị nào từ 1 đến n cho x[i] đều mặc nhiên được chấp nhận. Do vậy, trong bài toán này ta

Duyệt các cấu hình tổ hợp và ứng dụng Trang 30

Page 31: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

không cần quan tâm tới giá trị nào đã được chọn hay chưa. Ví dụ, các chỉnh hợp chập 3 (k=3) của 5 (n=5) giá trị 1,2,3,4,5 gồm nk = 53 =125 bộ nghiệm.

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

– Input: tệp Chlap.inp chứa hai số nguyên dương n và k.

– Output: tệp Chlap.out nhiều dòng, mỗi dòng chứa 1 số nguyên (là số tt chỉnh hợp lặp) và 1 cấu hình chỉnh hợp lặp.

Chlap.inp

3 2

Chlap.out 1: 1 1 2: 1 2 3: 1 3 4: 2 1 5: 2 2 6: 2 3 7: 3 1 8: 3 2 9: 3 3

{CHINH HOP LAP CHAP K CUA N}

uses crt;

const MaxN=100; { thử 100 phần tử}

fi='chlap.inp';{chua so N va k}

fo='chlap.out';{moi dong chua mot chinh hop lap}

Var

x:array[1..MaxN] of Integer;

n,k,d:integer;

f:text;

procedure Init;

var i:integer;

Begin

assign(f,fi);reset(f);

read(f,n,k);

close(f);

assign(f,fo);rewrite(f);

End;

Procedure Inkq;

var i:integer;

Duyệt các cấu hình tổ hợp và ứng dụng Trang 31

Page 32: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Begin

d:=d+1;write(f,d:4,': ');

for i:=1 to k do write(f,' ',x[i]); writeln(f);

End;

procedure Try(i:integer);

Var j:integer;

Begin

for j:=1 to n do

if b[j] then

begin

x[i]:=j;

if i=k then Inkq

else try(i+1);

end;

End;

BEGIN

Init;

try(1);

close(f);

END.

b. Chỉnh hợp không lặp

Phát biểu: Một chỉnh hợp không lặp chập k của n phần tử là một bộ có thứ tự gồm k thành phần khác nhau lấy từ n phần tử đã cho (n>1, k>0, n>k).

Vd: n=3, k=2. Các chỉnh hợp không lặp chập 2 của 3 phần tử trên: (1,2), (1,3), (2,1), (2,3), (3,1), (3,2)

Vd: n=4, k=3: cây liệt kê như sau:

Duyệt các cấu hình tổ hợp và ứng dụng Trang 32

Page 33: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Ta nhận thấy rằng, mỗi chỉnh hợp không lặp cũng có dạng X(x1, x2…xk). Các giá trị đề cử của xi (i=1..k) là từ 1..n. Tuy nhiên các thành phần là đôi một khác nhau (x i

<> xj: i<>j, i,j=1..k). Do vậy ta phải sử dụng một biến mảng B để quản lý các giá trị từ 1 đến n. nếu b[j] = true, chưa xét đến và ngược lại.

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

Input: tệp Chklap.inp chứa hai số nguyên dương n và k.

Output: tệp Chklap.out nhiều dòng, mỗi dòng chứa 1 số nguyên (là số tt chỉnh hợp lặp) và 1 cấu hình chỉnh hợp lặp.

Chklap.inp

3 2

Chklap.out 1: 1 2 2: 1 3 3: 2 1 4: 2 3 5: 3 1 6: 3 2

{CHINH HOP KHONG LAP CHAP K CUA N}

uses crt;

const MaxN=100;

fi='chklap.inp';{chua so N va K}

fo='chklap.out';{moi dong chua mot cau hinh}

var

x:array[1..MaxN] of Integer;

b:array[1..MaxN] of boolean;

n,k,d:integer;

f:text;

procedure Init;

var i:integer;

Begin

assign(f,fi);reset(f);

Duyệt các cấu hình tổ hợp và ứng dụng Trang 33

Page 34: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

read(f,n,k);

close(f);

for i:=1 to n do b[i]:=true;

assign(f,fo);rewrite(f);

End;

Procedure Inkq;

var i:integer;

Begin

d:=d+1;write(f,d:4,': ');

for i:=1 to k do write(f,' ',x[i]); writeln(f);

End;

procedure Try(i:integer);

Var j:integer;

Begin

for j:=1 to n do

if b[j] then

begin

x[i]:=j;

b[j]:=false;

if i=k then Inkq

else try(i+1);

b[j]:=true;

end;

End;

BEGIN

Init;

Try(1);

close(f);

END.

Duyệt các cấu hình tổ hợp và ứng dụng Trang 34

Page 35: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Để liệt kê toàn bộ chỉnh hợp không lặp chập k, k=1..N. của các tập con từ 1..N thì trong chương trình chính ta viết:

BEGIN

Init;

for k:=1 to n do Try(1);

close(f);

END.

c. Hoán vị

Phát biểu: Liệt kê các hoán vị của dãy số nguyên từ 1..N

Vd: Xem mục 1 phần Giải thuật quay lui.

Dùng mảng X để biểu diễn các hoán vị dạng x1x2…xn, trong đó với mỗi xi có thể nhận một trong các giá trị từ 1..N. Vì mỗi giá trị j=1..n chỉ xuất hiện một lần trong dãy X, nên ta dùng một mảng B để đánh dấu các giá trị, b j=true nếu j chưa được dùng. Áp dụng thuật toán đệ quy quay lui để tìm thành phần xi như sau:

Procedure Try(i:integer);

Var j:integer;

Begin

for j:=1 to n do {các khả năng mà xi có thể nhận}

if b[j] then {nếu j chưa được dùng (thoả P)}

begin

x[i]:=j;

if i=n then PrintResult {thoả Q}

else begin

b[j]:=false; {đánh dấu đã dùng}

Try(i+1);

b[j]:=true; {trả lại trạng thái cũ - giải phóng}

end

end;

End;

Yêu cầu về dữ liệu:

Dữ liệu vào: tệp văn bản Hoanvi.inp chứa số nguyên N

Duyệt các cấu hình tổ hợp và ứng dụng Trang 35

Page 36: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Kết quả: ghi vào tệp Hoanvi.out mỗi dòng chứa một hoán vị

Chương trình được viết như sau:Const

MaxN=100;fi='hoanvi.inp';{chua so N}fo='hoanvi.out';{moi dong chua mot hoan vi}

Varx:array[1..MaxN] of integer;b:array[1..MaxN] of boolean;n:integer;f:text;

procedure Init;

var i:integer;

Beginassign(f,fi);reset(f);read(f,n);for i:=1 to n do b[i]:=true;close(f);assign(f,fo);rewrite(f);

End;

Procedure PrintResult;

var i:integer;

Beginfor i:=1 to n do write(f,' ',x[i]); writeln(f);

End;

procedure Try(i:integer);

Var j:integer;

Beginfor j:=1 to n doif b[j] then

beginx[i]:=j;if i=n then PrintResultelse begin

b[j]:=false;try(i+1);

Duyệt các cấu hình tổ hợp và ứng dụng Trang 36

Page 37: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

b[j]:=true;end

end;

End;

BEGINInit;Try(1);Close(f);

END.

d. Tổ hợp

Phát biểu: Một tổ hợp chập k của n phần tử là một bộ không kể thứ tự gồm k thành phần khác nhau lấy từ n phần tử đã cho, hai thành phần bất kì trong bộ đó phải khác nhau. (n>1, k>0, n>k). Nói cách khác, một tổ hợp chập k của n phần tử là một tập con k phần tử của nó.

Ví dụ 7: chập 3 của 5 phần tử

Sử dụng mảng X(x1, x2…xk) chứa các phần tử của một tổ hợp chập k của N. Vấn đề là ta phải xác định xem giá trị của xi (i=1..n)là gì và có phải dùng kỹ thuật đánh dấu các giá trị đã được lựa chọn hay không.

– Quan sát từ hình vẽ: Xét một nút bất kỳ có giá trị A thì các nút tiếp theo thuộc nhánh trái nhất sẽ là A+1, nút phải nhất tối đa là N. Xét thêm một vài nhánh để xem có xác định mộ giá trị tốt hơn N không? Từ hình vẽ ta bổ sung thêm phần tử x0=0 là giá trị cho nút khởi đầu.

x0=0

i=1,xi=các đề cử mới(1, 2, 3), x0+1≤xi≤n-k+i, chọn x1=1

i=2,xi=các đề cử mới(2, 3, 4), x1+1≤xi≤n-k+i, chọn x2=2

i=3,xi=các đề cử mới(3, 4, 5), x2+1≤xi≤n-k+i,

chọn x3=3; i=k => một tổ hợp 1, 2, 3

chọn x3=4; i=k => một tổ hợp 1, 2, 4

Duyệt các cấu hình tổ hợp và ứng dụng Trang 37

Page 38: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

chọn x3=5; i=k => một tổ hợp 1, 2, 5

hết giá trị thoả mãn cho x3, quay lui xét lại x2 và đi theo hướng mới.

i=2,xi=các đề cử còn(3,4), x1+1≤xi≤n-k+i, chọn x2=3

i=3,xi=các đề cử mới(4,5), x2+1≤xi≤n-k+i,

chọn x3=4; i=k => một tổ hợp 1, 3, 4

chọn x3=5; i=k => một tổ hợp 1, 4, 5

hết giá trị thoả mãn cho x3, quay lui xét lại x2 và đi theo hướng mới.

i=2,xi=các đề cử còn(4), x1+1≤xi≤n-k+i, chọn x2=4

i=3,xi=các đề cử mới(5), x2+1≤xi≤n-k+i,

chọn x3=5; i=k => một tổ hợp 1, 4, 5

hết giá trị thoả mãn cho x3, quay lui xét lại x2; x2 hết lựa chọn, lui tiếp về x1 và đi theo hướng mới. (người đọc tự nghiên cứu tiếp)

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

(liệt kê mọi cấu hình tổ hợp chập k của n phần tử)

Mỗi một tổ hợp ta lưu vào một mảng X: 1≤x1≤…≤xk≤n. Suy ra giá trị đề cử cho xi là j=1..n hoặc xét kỹ hơn sẽ là j=xi-1+1..n-k+i (tự suy nghĩ).

– Dữ liệu vào file tohopK_N.inp: chứa số nguyên N

– Kết quả file tohopK_N.out mỗi dòng chứa một tổ hợp chập k của N

Chương trình liệt kê các tổ hợp chập k của N phần tử như sau:

Const MaxN=100;

fi='tohopK_N.inp';{chua so N}

fo='tohopK_N.out';

var

x:=array[0..MaxN] of longint;

n,k,d:integer;

f:text;

Procedure Init;

Var i:integer;

Begin

assign(f,fi);reset(f);

Duyệt các cấu hình tổ hợp và ứng dụng Trang 38

Page 39: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

read(f,n);

close(f);

assign(f,fo);rewrite(f);

x[0]:=0;

End;

Procedure PrintResult;

var i:integer;

Begin

d:=d+1;

write(f,d:4,': ');

for i:=1 to k do write(f,' ',x[i]);

writeln(f);

End;

procedure Try(i:integer);

Var j:integer;

Begin

for j:=x[i-1]+1 to n-k+i do {}

begin

x[i]:=j;

if i<k then try(i+1) else PrintResult;

end;

End;

BEGIN

Init;

for k:=1 to n do Try(1);

close(f);

END.

Duyệt các cấu hình tổ hợp và ứng dụng Trang 39

Page 40: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

(Chú ý: Bạn đọc hãy tìm hiểu kỹ các bài toán trên trong phần cài đặt chương trình tại các vị trí đã được đánh dấu nghiên, đậm và cũng có thể chưa đánh dấu. Vì nếu lướt qua ta sẽ thấy các bài này na ná giống nhau, nhưng thực chất là khác nhau) .

e. Bài toán dãy nhị phân.

Liệt kê các dãy nhị phân độ dài n

Minh hoạ bài toán trường hợp n=3 dưới dạng cây nhị phân sau:

Liệt kê các dãy có chiều dài n dưới dạng x1,x2...xn, trong đó xi={0,1}. Ta có thể sử dụng sơ đồ tìm tất cả các lời giải của bài toán. Hàm Try(i) xác định x i, trong đó xi

chỉ có 1 trong 2 giá trị là 0 hay 1. Các giá trị này mặc nhiên, được chấp nhận mà không cần phải thoả mãn điều kiện gì. Nên Hàm try(i) có thể viết như sau :

Procedure Try ( i);

Var I,j:integer;

Beginfor j = 0 to 1 dobegin

x[i]=j;if (i < n ) then Try (i+1);else PrintX;

end;

end;

Thủ tục PrintX: mỗi dãy nhị phân viết trên một dòng đặt trong tệp văn bản.

Procedure PrintX;

Var i:integer;

Begin

Duyệt các cấu hình tổ hợp và ứng dụng Trang 40

Page 41: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

For i:=1 to n do write(f, x[i]);

Writeln(f);

End;

Trong lời gọi của chương trình chính: Try(1);

f. Bài toán N quân hậu.

Hướng dẫn: xem lại ví dụ 2 phần 1

Cho bàn cờ vua NxN, hãy tìm tất cả các cách đặt N quân hậu lên bàn cờ sao cho không quân nào ăn được quân nào.

Mỗi dòng được đặt đúng một hậu đồng thời mỗi hậu cũng chỉ thuộc về một cột nên ta quy định mảng một chiều H chứa vị trí các quân hậu trên bàn cờ, trong đó h[i] là hậu thứ i đặt ở hàng i cột h[i] trên bàn cờ.

Mỗi quân hậu i có thể được đặt trên cột j=1..n, có nghĩa là h[i]=j sao cho ô (i,j) chưa bị hậu nào khống chế. Để kiểm soát điều này theo luật cờ Hậu ăn ngang, dọc và theo hai đường chéo.

Mỗi hậu được đặt trên một hàng i, nên không cần kiểm tra hàng. Ta sẽ dùng mảng c để kiểm soát các cột trên bàn cờ, c[j]=true có nghĩa trên cột j chưa đặt hậu nào. Các ô nằm trên cùng một đường chéo song song với đường chéo phụ, đều có i+j=C1 (hằng số) với 2<=C1<=2n. Các ô cùng nằm trên đường chéo song song với đường héo chính lại có i-j=C2 với 1–n<=C1<=n-1. do vậy để kiểm soát 2 đường chéo ta dùng 2 biến c1[i+j]=true, c2[i-j]=true nếu ô (i,j) chưa bị hậu nào không chế theo đường chéo.

Tóm lại nếu c[i]=c1[i+j]=c2[i-j]=true thì có thể đặt hậu i vào cột j.

Dữ liệu: Hau.inp chứa kích thức bàn cờ số nguyên n

Kết quả: Hau.out các vị trí hậu trên từng bàn cờ.

{Chương trình xếp n hậu}

Duyệt các cấu hình tổ hợp và ứng dụng Trang 41

Page 42: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

const MaxN=10;

fi='hau.inp';{chua so N}

fo='hau.out';

var

h:array[1..MaxN] of integer;

c:array[1..MaxN] of boolean;

c1:array[2..2*MaxN] of boolean;

c2:array[1-MaxN..MaxN+1] of boolean;

n:integer;

f:text;

procedure Init;

var i,j:integer;

Begin

assign(f,fi);reset(f);

read(f,n);

for i:=1 to n do c[i]:=true;

for i:=2 to 2*n do c1[i]:=true;

for i:=1-n to n+1 do c2[i]:=true;

close(f);

assign(f,fo);rewrite(f);

End;

Procedure PrintResult;

var i,j:integer;

Begin

writeln(f,'==========');

for i:=1 to n do begin

for j:=1 to n do if h[i]=j then write(f,'H') else write(f,'O');

writeln(f);

end;

writeln(f);

Duyệt các cấu hình tổ hợp và ứng dụng Trang 42

Page 43: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

End;

procedure Try(i:integer);

Var j,k:integer;

Begin

for j:=1 to n do

if c[j] and c1[i+j] and c2[i-j] then

begin

h[i]:=j;

if i=n then PrintResult

else begin

c[j]:=false;c1[i+j]:=false;c2[i-j]:=false;

Try(i+1);

c[j]:=true;c1[i+j]:=true;c2[i-j]:=true;

end;

end;

End;

BEGIN

Init;

Try(1);

close(f);

END.

với n=4, kết quả tệp hau.out như sau:

==========

OHOO

OOOH

HOOO

OOHO

==========

OOHO

HOOO

Duyệt các cấu hình tổ hợp và ứng dụng Trang 43

Page 44: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

OOOH

OHOO

g. Bài toán Ngựa đi tuần

Phát biểu bài toán

Cho bàn cờ có n x n ô . Một con ngựa được phép đi theo luật cờ vua, đầu

tiên được đặt ở ô có tọa độ x0 , y0 . Hãy chỉ ra các hành trình (nếu có) của ngựa – Đó là ngựa đi qua tất cả các ô của bàn cờ, mỗi ô đi qua đúng một lần .

Thiết kế thuật toán

Cách giải quyết rõ ràng là xét xem có thể thực hiện một nước đi kế nữa hay không. Sơ đồ đầu tiên có thể phát thảo như sau :

Procedure Try(i);

Begin

for ( j = 1 … k)

If ( xi chấp nhận được khả năng k)

begin

Xác định xi theo khả năng k;

Ghi nhận trạng thái mới;

if( i < n2 ) Try(i+1)

else Ghi nhận nghiệm;

rả lại trạng thái cũ cho bài toán;

end;

End;

Để mô tả chi tiết thuật toán, ta phải qui định cách mô tả dữ liệu và các thao tác, đó là :

Biểu diễn bàn cờ .

Các khả năng chọ lựa cho xi ?

Cách thức xác định xi theo j.

Cách thức gi nhận trạng thái mới, trả về trạng thái cũ.

Ghi nhận nghiệm.

. . .

Duyệt các cấu hình tổ hợp và ứng dụng Trang 44

Page 45: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Ta sẽ biểu diễn bàn cờ bằng 1 ma trận vuông cấp n : int Ma[n][n];

Sở dĩ thể hiện mỗi ô cờ bằng 1 số nguyên thay cho giá trị boole (để đánh

dấu ô đã được đi qua chưa) là vì ta muốn lần dò theo quá trình di chuyển của con ngựa.

Ta qui ước như sau :

Ma[x,y] = 0, Ô <x,y> ngựa chưa đi qua;

Ma[x,y] = i, Ô <x,y> ngựa đã đi qua ở bước thứ i (1 ≤ i ≤ n2 ).

Các khả năng chọn lựa cho xi ? Đó chính là các nước đi của ngựa mà xi có thể chấp nhận được. Với cặp tọa độ bắt đầu <x,y> như trong hình vẽ, có tất cả 8 ô <u,v> mà con ngựa có thể đi đến. Giả sử chúng được đánh số từ 1 đến 8 như hình sau :

( 8 bước đi có thể có của con ngựa )

Một phương pháp đơn giản để có được u, v từ x, y là ta dùng 2 mảng a và b lưu trữ các sai biệt về tọa độ .Nếu ta dùng một chỉ số k để đánh số “bước đi kế ” thì chi tiết đó được thể hiện bởi : u = x +a[k]; v = y + b[k]; k=0..7 .

Điều kiện “chấp nhận được” có thể được biểu diễn như kết hợp của các điều kiện :

Ô mới phải thuộc bàn cờ (1≤u ≤n và 1 ≤v≤n) và chưa đi qua ô đó, nghĩa là Ma[u,v] = 0;

Để ghi nhận nước đi hợp lệ ở bước i, ta gán Ma[u][v] = i; và để hủy một nước đi thì ta gán Ma[u][v] = 0.

Ma trận h ghi nhận kết quả nghiệm. Nếu có <x,y> sao cho Ma<x,y> = 0 thì đó không phải là lời giải của bài toán , còn ngược là Ma chứa đường đi của ngựa.

Vậy thuật toán có thể mô tả như sau :

Input n, //Kích thước bàn cờ x, y;//Toạ độ xuất phát ở bước i

Output Ma;

Duyệt các cấu hình tổ hợp và ứng dụng Trang 45

Page 46: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Procedure Try(i, x, y:integer);

Var u,v,k:integer;

Begin

For k = 1 to 8 do

Begin

u = x + a[k];

v = y + b[k];

if (1 <= u )and(v <= n)and(Ma[u][v] == 0) then

begin

Ma[u][v] = i;

if (i <= n*n) then Try(i+1,u,v)

else PrintH();

end;

Ma[u][v] = 0;

End;

End;

Thủ tục này xuất tất cả các lời giải, nếu có.

Thủ tục đệ qui được khởi động bằng một lệnh gọi các tọa độ đầu [x0][y0] là tham số. Ô xuất phát có trị 1, còn các ô khác được đánh dấu còn trống.

Ma[x0][y0] = 1; Try(2,x0, y0);

Các mảng a và b có thể khởi đầu như sau :

int a[8]= {2,1,-1,-2,-2,-1,1,2};

int b[8]= {1,2,2,1,-1,-2,-2,-1};

Các lời giải sau là một số kết quả cho từ thuật toán trên :n=5 x=1 y=1

1 6 15 10 2114 9 20 5 1619 2 7 22 118 13 24 17 425 18 3 12 23

Với n = 5, các tọa độ xuất phát sau không có lời giải : (2,3), (3,2)...

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

Duyệt các cấu hình tổ hợp và ứng dụng Trang 46

Page 47: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

{Duong di cua QuanMa tren ban co vua, moi o di qua 1 lan}

Usescrt;

Const MaxN=10;

fi='quanma.inp';{n/x y}

fo='quanma.out';

a:array[1..8] of integer=(2,1,-1,-2,-2,-1,1,2);

b:array[1..8] of integer=(1,2,2,1,-1,-2,-2,-1);

Var

n,d,x,y,u,v:integer;

ma:array[1..MaxN,1..MaxN] of integer;{thu tu quan ma}

f:text;

Procedure Init;

Var i,j:integer;

Begin

assign(f,fi);reset(f);

readln(f,n); read(f,x);read(f,y);

for i:=1 to n do for j:=1 to n do ma[i,j]:=0;

ma[x,y]:=1;

close(f);

assign(f,fo);rewrite(f);d:=0;

End;

Procedure PrintResult;

Var i,j:integer;

Begin

d:=d+1;

writeln(f,'=====',d,'=====');

for i:=1 to n do begin

for j:=1 to n do write(f,ma[i,j]:2,'.');

writeln(f);

end;

Duyệt các cấu hình tổ hợp và ứng dụng Trang 47

Page 48: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

writeln(f);

End;

Procedure Try(i:integer;x,y:integer);

Var j,k,u,v:integer;

Begin

for j:=1 to 8 do

begin

u:=x+a[j];

v:=y+b[j];

if (ma[u,v]=0)and(u>=1)and(u<=n)and(v>=1)and(v<=n) then

begin

ma[u,v]:=i;

if i=n*n then PrintResult

else Try(i+1,u,v);

ma[u,v]:=0;

end;

end;

End;

BEGIN

Init;

Try(2,x,y);

Close(f);

END.

h. Mê cung (later)

Quay lui là ban đầu ta tiến, tiến và tiến cho đến khi không tiến được nữa thì lui và lui cho đến khi có đường đi mới, ta lại tiến và tiến… lại lui, lui cho đến khi hết đường lui. Hết việc!

Duyệt các cấu hình tổ hợp và ứng dụng Trang 48

Page 49: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

4. Tài liệu tham khảo.

a. Thầy nguyễn Thanh Tùng tóm tắt về TÌM KIẾM QUAY LUI.

Tìm kiếm quay lui (Backtraking) là phương pháp tìm kiếm lời giải trên cây phương án. Phương pháp này được sử dụng chủ yếu để tìm một lời giải thỏa mãn một số yêu cầu nào đó theo nguyên tắc mở rộng dần dần lời giải.

Các bài toán điển hình:

Mã đi tuần: Tìm đường đi của quân mã trên trên bàn cờ kích thước NN, sao cho mỗi ô trên bàn cờ (trừ ô xuất phát) được đi qua đúng một lần và trở về ô xuất phát,

Đặt quân hậu: Đặt ttối đa số quân hậu trên bàn cờ NN, sao cho không có hai quân hậu nào ở vị trí ăn nhau,

Bài toán người bán hàng rong: Tìm đường đi khép kín ngắn nhất qua mỗi đỉnh của đồ thị đúng một lần,

Xâu không lặp: Với M ký tự khác nhau hãy tìm xâu có độ dài N, sao cho mọi xâu con L ký tự liên tiếp đều khác nhau,

Xâu phản đối xứng: Với M ký tự khác nhau hãy tìm xâu có độ dài N, sao cho nếu lấy xâu con bất kỳ các ký tự liên tiếp nhau và chia nó thành hai xâu con liên tiếp nhau, thì hai xâu con mới này khác nhau với mọi cách chia,

Thoát khỏi mê cung: Điều khiển rô bốt tìm đường ra khỏi mê cung.

Nguyên tắc cơ bản của phương pháp tìm kiếm quay lui là như sau:

Chia tập tìm kiếm thành nhiều tập con,

Đánh số các tập con theo một tiêu chuẩn nào đó có các tập P1, P2, . . ., Pk,

PP1 P2

P3

P11P12

P14

Với mỗi tập con nhận được: xác định một trong số các khả năng:

Không cần xét tiếp tập này,

Bài toán trở nên quá đơn giản và tìm được một lời giải,

Duyệt các cấu hình tổ hợp và ứng dụng Trang 49

Page 50: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Qay lại bước a) với tập con này.

Tiêu chuẩn phân chia tập con: thỏa mãn một trong số các tính chất:

Nhận được bài toán giống như ban đầu, nhưng có kích thước bé hơn,

Nhận được bài toán đơn giản hơn,

Nhận được bài toán với một số tính chất mới không có trong bài toán ban đầu.

Tiêu chuẩn đánh số các tập con:

Theo thứ tự từ điển của một cấu trúc dữ liệu,

Theo khả năng, triển vọng tồn tại nghiệm.

Tìm kiếm quay lui về bản chất gần giống các giải thuật đệ quy, nhưng có một số khác biệt cơ bản:

Người lập trình điều khiển được quá trình duyệt theo các hướng có triển vọng,

Không cần lưu toàn bộ các nút rẽ nhánh trong tìm kiếm,

Có thể dễ dàng ngắt và quay lui khi cần thiết.

Chính vì những đặc điểm trên nên giải thuật này thường áp dụng để giải các bài toán theo phương pháp nhánh và cận.

Các mô đun cơ bản:

Khởi tạo tìm kiếm quay lui: init,

Mở rộng lời giải : Extend,

Chuyển sang tập mới: Change,

Kiểm tra tính hợp lệ của lời giải : Check.

Sơ đồ chung :

init ;

repeat

Extend ;

Check ;

While not ok do

begin

change;

check

end;

Duyệt các cấu hình tổ hợp và ứng dụng Trang 50

Page 51: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

until kt;

b. Các tác giả khác

– Nguyễn Đức Nghĩa, Nguyễn Tô Thành. Toán rời rạc, NXB ĐHQGHN, 2003

– ThS.Trần Đức Huyên. Phương pháp giải các bài toán trong Tin học. NXBGD. 2004.

– Nguyễn Xuân Huy. Sáng tạo trong thuật toán và lập trìng. NXBGD. 2007.

– Lê Minh Hoàng. Giải thuật và lập trình – A.D.A DSAP Textbook, DHSPHN, 1999-2002. <Internet>

– Trần Tuấn Minh. Thiết kế và đánh giá thuật toán. Đà lạt. <Internet>

– Lê Minh Hoàng. Bài giảng các chuyên đề.

Duyệt các cấu hình tổ hợp và ứng dụng Trang 51

Page 52: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

PHẦN IV. ỨNG DỤNG

I. KHÁI NIỆM BÀI TOÁN TỐI ƯU.

1. Một số khái niệm

* Phát biểu bài toán: Có nhiều bài toán mà việc giải nó đưa về việc duyệt các cấu hình tổ hợp thoả mãn các điều kiện nào đó. Với mỗi cấu hình tổ hợp, ta sẽ tính toán theo một cách nào đó (tuỳ theo yêu cầu của bài toán) để được một giá trị bằng số. Giá trị đó thể hiện giá trị sử dụng của cấu hình (gọi là giá của cấu hình hay giá của phương án).

* Bài toán đặt ra: “Trong số các cấu hình tổ hợp chấp nhận được, hãy lựa chọn một cấu hình có giá trị sử dụng tốt nhất (lớn nhất hoặc nhỏ nhất”

Các bài toán như vậy gọi là bài toán tối ưu tổ hợp.

a. Phương án và giá của phương án

Mỗi cấu hình tổ hợp gọi là một phương án của bài toán (hay còn gọi là một lời giải của bài toán). Với mỗi phương án của bài toán ta tính toán được một con số gọi là giá của phương án.

b. Hàm mục tiêu của bài toán

Nếu ta gọi tập các phương án của bài toán là D.

Khi đó, với mỗi phương án x thuộc D cho chúng ta một giá trị số duy nhất tương ứng với nó. Do đó xác định một hàm số:

f : D R

x y=f(x)

Hàm f(x) như vậy gọi là hàm mục tiêu của bài toán

Vậy: Bài toán tối ưu tổ hợp là bài toán: “Tìm Max{f(x)| xD}” hoặc “Tìm Min{f(x)| |xD}”, với D là tập các phương án của bài toán.

c. Giá trị tối ưu và phương án tối ưu

Một phương án x*D mà tại đó f(x*) đạt giá trị min hoặc max gọi là phương án tối ưu của bài toán.

Giá trị f(x*) gọi là giá trị tối ưu của bài toán. Như vậy:

Với bài toán tìm max thì: f(x*) lớn hơn hoặc bằng f(x) với mọi x thuộc D;

Với bài toán tìm min thì: f(x*) nhỏ hơn hoặc bằng f(x) với mọi x thuộc D;

Chú ý:

Duyệt các cấu hình tổ hợp và ứng dụng Trang 52

Page 53: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Giá trị tối ưu của bài toán là duy nhất.

Phương án tối ưu của bài toán có thể có nhiều

d. Các ví dụ

Ví dụ 1: Bài toán cái túi

Một nhà thám hiểm cần đem theo một cái túi có trọng lượng không quá b. Có n đồ vật cần đem theo. Đồ vật thứ j có trọng lượng là aj và giá trị sử dụng là cj (j = 1, 2, 3, ..,n). Hỏi rằng nhà thám hiểm cần đem theo các đồ vật nào để cho tổng giá trị sử dụng của các đồ vật đem theo là lớn nhất?

Dữ liệu: Vào từ file văn bản CAITUI.INP:

Dòng đầu ghi 2 số nguyên dương n và b (n < 100).

Dòng thứ hai ghi các số nguyên không âm a1, a2, .. ,an.

Dòng thứ ba ghi các số nguyên không âm c1, c2, .. ,cn.

Kết quả: Ghi ra file CAITUI.OUT:

Dòng đầu ghi tổng giá trị các đồ vật đem theo ứng với phương án tìm được.

Ghi chỉ số của các đồ vật đem theo

Ví dụ:

CAITUI.INP CAITUI.OUT

4 8

5 3 2 4

10 5 3 6

15

1 2

Phân tích:

– Mỗi đồ vật chỉ có 2 khả năng lựa chọn (2 trạng thái) là: được chọn vào túi để mang đi hoặc không được chọn vào túi để mang đi.

Do đó, mỗi phương án chọn đồ vật để mang theo của nhà thám hiểm là một bộ x=(x1,x2,…,xn), trong đó xi = 0 hoặc 1, i=1,2,…,n; Với ý nghĩa xi = 0 tương đương với việc đồ vật i không được chọn vào túi, còn xi = 1 tương đương với việc đồ vật i được chọn vào túi.

Như vậy, mỗi phương án lựa chọn các đồ vật là một chỉnh hợp lặp chập n của 2 phần tử {0,1} (hay một dãy nhị phân độ dài n).

Điều kiện chấp nhận của phương án x là “tổng khối lượng các đồ vật được chọn

nhỏ hơn hoặc bằng b”, tức là: g(x) = < b

Duyệt các cấu hình tổ hợp và ứng dụng Trang 53

Page 54: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Giá của phương án x bằng: f(x) =

Kết luận:

Bài toán cái túi là một bài toán tối ưu tổ hợp: “Tìm Max{f(x)| xD}, với D={x|x=(x1,x2,…,xn), xi = 0 hoặc 1, i=1,2,…,n; và g(x) < b}

Ví dụ 2: Bài toán thuê thợ

Có n công việc được đánh số từ 1 đến n và có n thợ được đánh số từ 1 đến n.

Mỗi công việc i biết chi phí cần trả để thợ j hoàn thành công việc này là c[i,j], với i,j = 1,2,3,..,n.

Yêu cầu: Hãy tìm phương án thuê thợ với tổng chi phí phải trả là nhỏ nhất sao cho các công việc đều hoàn thành, biết rằng mỗi thợ chỉ thực hiện một công việc và mỗi việc chỉ do một thợ thực hiện.

Dữ liệu: Vào từ file văn bản THUETHO.INP có dạng

Dòng đầu ghi số n. (N <= 100)

n dòng tiếp theo, mỗi dòng i ghi n số c[i,j], j = 1,2…,n tương ứng là chi phí cần trả để thợ j hoàn thành công việc i (i = 1,2,…,n).

Kết quả: Ghi ra file văn bản THUETHO.OUT gồm:

Dòng đầu ghi tổng chi phí thuê thợ.

Dòng thứ 2 ghi n số, trong đó số thứ i (i=1,2,..n) là số hiệu của thợ thực hiện công việc i.

Ví dụ: THUETHO.INP THUETHO.OUT54 8 17 19 712 6 17 19 108 19 19 7 717 9 17 3 77 16 12 16 8

321 2 5 4 3

*Phân tích:

– Mỗi phương án thuê thợ là một hoán vị của n phần tử {1,2, ...,n}. Kí hiệu x={x1,x2, ...,xn} trong đó xi = j nghĩa là việc i thuê thợ j; i=1,2,..,n; j {1,2, ...,n}.

– Tập các phương án: D = {x| x = {x1,x2, ...,xn}, xi {1,2, ...,n}, i=1,2,..,n và xi<>xj nếu i<>j }

– Giá của phương án: f(x) =

Duyệt các cấu hình tổ hợp và ứng dụng Trang 54

Page 55: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Bài toán đưa về bài toán tối ưu tổ hợp: “Tìm Min{f(x)| x D}”

2. Một số phương pháp giải bài toán tối ưu tổ hợp

* Phương pháp duyệt

Dùng kiến thức toán học đã biết, dùng suy luận, đánh giá

đưa ra được phương án tối ưu.

* Phương pháp đánh giá nhánh cận

* Cặp ghép

....

Duyệt các cấu hình tổ hợp và ứng dụng Trang 55

Page 56: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

II. PHƯƠNG PHÁP DUYỆT GIẢI BÀI TOÁN TỐI ƯU

1. Tư tưởng chủ đạo

Lần lượt duyệt các cấu hình của bài toán. Đối với mỗi cấu hình thoả mãn điều kiện của bài toán (mỗi phương án của bài toán) ta đi tính giá của phương án đó. So sánh giá của tất cả các phương án với nhau để tìm ra phương án tối ưu và giá trị tối ưu.

Trong quá trình duyệt ta luôn giữ lại phương án tốt hơn. Phương án tốt nhất cho đến thời điểm đang duyệt gọi là phương án mẫu. Giá trị của phương án mẫu gọi là kỷ lục tạm thời.

Khi duyệt xong tất cả các phương án thì sẽ tìm được phương án tối ưu và giá trị tối ưu. Tuy nhiên, trên thực tế với những bài toán có kích thước lớn (số phương án nhiều) thì thời gian duyệt lâu dẫn đến không khả thi. Do đó, trong quá trình duyệt ta nên hạn chế bớt phép duyệt (không duyệt các phương án mà ta đã biết chắc chắn rằng phương án đó không thể là phương án tối ưu của bài toán).

Có hai cách duyệt:

Duyệt toàn bộ (vét cạn)

Duyệt hạn chế (phương pháp duyệt có đánh giá nhánh cận)

2. Cấu trúc của phương pháp duyệt tổng quát

*Phát biểu bài toán tối ưu tổ hợp bằng cách khác:

Tìm MAX{f(x), x thuộc D} hoặc Tìm MIN{f(x), x thuộc D}

trong đó:

+) D = {x| x=(x1,x2, ..., xn) A1 × A2 ×... ×An ; x thoả mãn tính chất P}

+) A1 , A2 ,... ,An là các tập hữu hạn phần tử.

+) Ai là tập gồm các khả năng đề cử cho thành phần xi

* Phương pháp duyệt viết dưới dạng mô hình quay lui có cấu trúc tổng quát như sau:

Procedure Khởitạo;

begin

Đọc dữ liệu vào

Khởi tạo các giá trị ban đầu cho các biến

end;

Duyệt các cấu hình tổ hợp và ứng dụng Trang 56

Page 57: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

{}Procedure Cập Nhật Kỷ Lục;

begin

- <Tính giá phương án nếu chưa tính>

- Nếu giá p/án > kỷ lục (hoặcp/án > kỷ lục) thì

begin

kỷ lục := giá p/án;

giữ lại p/án;

end;

end;

Procedure Try(k : integer);

begin

for ak Ak do

if <chấp nhận ak> then

begin

xk := ak;

<Tính giá của phương án bộ phận cấp k;>

<Xác định trạng thái mới của bài toán nếu cần>

if k = n then Cập Nhật Kỷ Lục

else try(k+1);

<Hoàn nguyên trạng thái của bài toán nếu cần>

end;

end;

Procedure Inkq;

begin

<in kỷ lục và phương án tối ưu>

end;

BEGIN

Khởitạo;

Try(1);

Duyệt các cấu hình tổ hợp và ứng dụng Trang 57

Page 58: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

inkq;END.

III. BÀI TẬP ÁP DỤNG

Bài 1: Cân thăng bằng

Có một cái cân đĩa (cân thăng bằng) và n quả cân trọng lượng khác nhau (các quả cân được đánh số từ 1 đến n). Quả cân số hiệu i có trọng lượng a i. Người ta muốn cân một vật có trọng lượng p. Hãy tìm cách đặt vật và các quả cân lên đĩa để cân thăng bằng sao cho số quả cân phải dùng là ít nhất.

Dữ liệu:Vào từ file CAN.INP gồm 3 dòng:

Dòng đầu ghi số n.

Dòng thứ 2 ghi các số a1, a2, … ,an.

Dòng cuối cùng ghi giá trị p. Các số ai và p là nguyên dương. Giới hạn n < 30, a1 + a2 + …+an < 32767

Kết quả: Ghi ra file CAN.OUT

Nếu không có phương án đặt thì ghi số -1 tại dòng đầu tiên, trái lại kết quả ghi trên 2 dòng.

Dòng đầu gồm: số quả cân đặt cùng trên một đĩa với vật, tiếp theo là số hiệu của các quả cân này.

Dòng thứ 2 gồm: số quả cân đặt trên đĩa còn lại, tiếp theo là số hiệu của các quả cân này.

Trong các tệp dữ liệu các số trên cùng một dòng ghi cách nhau bởi dấu cách.

Ví dụ:CAN.INP CAN.OUT1027 10 73 95 60 55 87 77 75131

2 2 32 4 5

*Phân tích thuật toán:

Mỗi quả cân có 3 khả năng lựa chọn (hay còn gọi là có 3 trạng thái) được kí hiệu là 0,1,2, đó là: không đặt vào đĩa nào (0), đặt ở đĩa có vật (1), đặt ở đĩa không có vật (2);

Mỗi phương án (mỗi cấu hình) của bài toán là bộ: x[1], x[2], …, x[n] trong đó x[i] là khả năng lựa chọn của quả cân i: x[i] = 0,1,2 (i=1..n).

Duyệt các cấu hình tổ hợp và ứng dụng Trang 58

Page 59: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Bài toán đưa về duyệt các chỉnh hợp lặp chập n của 3 phần tử {0,1,2}, tính giá của từng phương án và cập nhật kỷ lục để giữ lại phương án tốt nhất.

Để tăng hiệu quả trong việc duyệt trước hết ta sắp xếp các quả cân giảm dần theo trọng lượng và thứ tự đề cử cho mỗi thành phần x[i] là 0, 1, 2.

Cách 1: Không dùng thêm tham số trong thủ tục Try{ chay cham ,n < 50}Program CanThangBang;uses crt;const fi ='can.inp'; fo ='can.out'; maxn=300;var a,a1 :array[1..maxn] of integer; kqx1,kqx2,x1,x2 :array[1..maxn] of integer; tongtua :array[1..maxn] of longint;{tongtua[i] := a[i+1] + a[i+2] + … + a[n]} n, p :integer; le, ri :longint;{tổng khối lượng các quả cân được đặt vào đĩa chứa vật và đĩa không chứa vật

của phương án bộ phận, ban đầu le := p; ri :=0} min,t,d,d1,d2,kqd1,kqd2 :integer; f:text; cs :array[1..maxn] of integer;Procedure init;var i:integer;Begin assign(f,fi); reset(f); readln(f,n); for i:=1 to n do read(f,a[i]); a1:=a; readln(f,p); close(f); le := p; ri := 0; min := maxint; d1 := 0; d2 := 0; tongtua[n]:=a[n]; for i:=n-1 downto 1 do tongtua[i]:=tongtua[i+1]+a[i];end;

Duyệt các cấu hình tổ hợp và ứng dụng Trang 59

Page 60: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

{------------------------------*****---------------------------}procedure Sort;var i,j,tg: integer;begin for i:=1 to n do cs[i]:=i; for i:=1 to n-1 do for j:=i+1 to n do if a[j]>a[i] then begin tg:=a[i];a[i]:=a[j];a[j]:=tg; tg:=cs[i];cs[i]:=cs[j];cs[j]:=tg; end; tongtua[n]:=a[n]; for i:=n-1 downto 1 do tongtua[i]:=tongtua[i+1]+a[i];end;Procedure cnkl;Begin if d < min then Begin min := d; kqd1 := d1; kqd2 := d2; kqx1 := x1; kqx2 := x2; End;End;Procedure try(i:integer);var j:integer;Begin for j:=0 to 2 do Begin if j=1 then Begin inc(d1); x1[d1] := i; le :=le + a[i]; End; if j=2 then Begin inc(d2); x2[d2] := i;

Duyệt các cấu hình tổ hợp và ứng dụng Trang 60

Page 61: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

ri := ri + a[i]; End; d:=d1+d2; if i=n then Begin if le=ri then cnkl; End else if (d < min) and (abs(le - ri) <= tongtua[i + 1]) then try(i + 1); if j=1 then Begin dec(d1); le := le - a[i]; End; if j=2 then Begin dec(d2); ri := ri - a[i]; End; d := d1 + d2; end;End;Procedure result;var i:integer;Begin assign(f,fo); rewrite(f); write(f,kqd1,' '); for i:=1 to kqd1 do write(f,cs[kqx1[i]],' '); writeln(f); write(f,kqd2,' '); for i:=1 to kqd2 do write(f,cs[kqx2[i]],' '); close(f);End;BEGIN init; sort; try(1); result;END.

Cách 2: Dùng thêm tham số trong thủ tục Try

Mỗi quả cân có 3 khả năng lựa chọn (hay còn gọi là có 3 trạng thái) được kí hiệu là 1,0,-1, đó là: đặt ở đĩa có vật (1), không đặt vào đĩa nào (0), đặt ở đĩa không có vật (-1);

Duyệt các cấu hình tổ hợp và ứng dụng Trang 61

Page 62: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Mỗi phương án (mỗi cấu hình) của bài toán là bộ: x[1], x[2], …, x[n] trong đó x[i] là khả năng lựa chọn của quả cân i: x[i] = -1,0,1 (i=1..n).

Trong thủ tục Try: S là khối lượng chênh lệch giữa hai đĩa cân ở bước i-1 truyền lại cho bước thứ i, sau đó được tính lại khi đã chọn xong ở bước i và truyền lại cho bước i+1

program CanThangBang;uses crt;const fin='Can.inp'; fout='Can.out'; maxn=70;var a,cs : array[1..maxn] of integer; x,kqx : array[1..maxn] of integer; ts : array[1..maxn] of longint;{tổng sau ts[i]:=a[i+1]+a[i+2]+…+a[n]} n,d,t : integer; min,kqi : integer; f : text; p,s:longint;{s là chênh lệch khối lượng giữ hai đĩa cân, được khởi tạo ban đầu là p}{d là số quả cân được chọn đặt lên đĩa}procedure Init;var i: integer;begin assign(f,fin);reset(f); readln(f,n); for i:=1 to n do read(f,a[i]); readln(f); readln(f,p); close(f); min:=maxint; s:=p; d:=0; t:=0;end;procedure Sort;var i,j,tg: integer;begin for i:=1 to n do cs[i]:=i; for i:=1 to n-1 do for j:=i+1 to n do if a[j]>a[i] then

Duyệt các cấu hình tổ hợp và ứng dụng Trang 62

Page 63: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

begin tg:=a[i];a[i]:=a[j];a[j]:=tg; tg:=cs[i];cs[i]:=cs[j];cs[j]:=tg; end; ts[n]:=0; for i:=n-1 downto 1 do ts[i]:=a[i+1]+ts[i+1];end;Procedure Try(i,s,d: integer);{d là số quả cân đã dùng đến bước i-1 truyền lại cho bước i}var j: integer;begin for j:=1 downto -1 do if d+abs(j)<min then {có thể đánh giá ngay tại đây: nếu thêm 1 quả cân nữa

đặt vào đĩa mà không tốt hơn kỷ lục của phương án mẫu thì không xây dựng tiếp pa} begin t:=s-j*a[i]; if abs(t)<=ts[i] then {độ lệch phải < tổng các quả cân chưa chọn} begin x[i]:=j; if t=0 then if d+abs(j)<min then begin min:=d+abs(j); kqi:=i; kqx:=x; exit; end; if i<n then Try(i+1,t,d+abs(j)); end; end;end;procedure Result;var c1,c2,i: integer;begin assign(f,fout);rewrite(f); if min=maxint then writeln(f,-1) else begin c1:=0;c2:=0; for i:=1 to kqi do begin

Duyệt các cấu hình tổ hợp và ứng dụng Trang 63

Page 64: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

if kqx[i]=-1 then inc(c1); if kqx[i]=1 then inc(c2); end; write(f,c1,' '); for i:=1 to kqi do if kqx[i]=-1 then write(f,cs[i],' '); writeln(f); write(f,c2,' '); for i:=1 to n do if kqx[i]=1 then write(f,cs[i],' '); end; close(f);end;BEGIN Init; Sort; Try(1,p,0); Result;END.

Bài 2 : Lập lịch ưu tiên đúng hạn.

Có n công việc được đánh số từ 1 đến n và có một máy để thực hiện chúng. Biết:

+ pi là thời gian cần thiết để hoàn thành công việc i.

+ di là thời hạn hoàn thành công việc i.

Mỗi công việc cần được thực hiện liên tục từ lúc bắt đầu cho tới khi kết thúc, không cho phép ngắt quãng. Khoảng thời gian thực hiện hai công việc bất kì chỉ được có nhiều nhất 1 điểm chung. Thời điểm bắt đầu thực hiện n công việc tính từ 0. Giả sử ci là thời điểm hoàn thành công việc i. Khi đó, nếu ci > di ta nói công việc i bị hoàn thành trễ hạn, còn nếu nếu ci < di ta nói công việc i bị hoàn thành đúng hạn.

Yêu cầu: Tìm trình tự thực hiện các công việc sao cho số công việc được hoàn thành đúng hạn là lớn nhất.

Dữ liệu: Vào từ file văn bản LIC* HDH.INP:

+ Dòng đầu tiên chứa số nguyên dương n (0 < n < 100).

+ Dòng thứ 2 chứa n số nguyên dương p1, p2, … , pn.

+ Dòng thứ 3 chứa n số nguyên dương d1, d2, … , dn.

Kết quả: Ghi ra file LIC* HDH.OUT gồm:

+ Dòng đầu tiên ghi số lượng công việc được hoàn thành đúng hạn theo trình tự tìm được.

+ Dòng tiếp theo ghi trình tự thực hiện các công việc đã cho.

Duyệt các cấu hình tổ hợp và ứng dụng Trang 64

Page 65: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Ví dụ:

LIC* HDH.INP LIC* HDH.OUT

6

4 1 2 3 1

5 6 6 7 8

4

1 3 4 6 2 5

*Phân tích thuật toán:

- Một trình tự thực hiện các công việc (một phương án của bài toán) là một hoán vị của n phần tử {1, 2, …, n}.

Cụ thể: mỗi phương án là 1 bộ x = (x1, x2, …,xn); trong đó xi {1, 2, …, n}, xi <> xj nếu i<>j;

- Giá của phương án x (số công việc đúng hạn) bằng: f(x) = k

Với điều kiện g(x) = < di với mọi i = 1,2, …, k

Bài toán lập lịch đúng hạn đưa về bài toán: “Tìm Max{f(x)| xD},

với D={x|x=(x1,x2,…,xn), xi {1, 2, …, n}, xi <> xj nếu i<>j; và g(x) < di}

Văn bản chương trình:program LapLichUuTienDungHan;uses crt;const fin = 'LIC* HD.INP'; fout = 'LIC* HD.OUT'; maxn = 100;var p,d,x,kqx : array[1..maxn] of integer; cx,kqcx : array[1..maxn] of boolean; f : text; n : integer; tg,count,max: integer;{----------------------------------------------------------}procedure Init;var i: integer;begin assign(f,fin);reset(f); readln(f,n); for i:=1 to n do read(f,p[i]); readln(f); for i:=1 to n do read(f,d[i]); close(f);

Duyệt các cấu hình tổ hợp và ứng dụng Trang 65

Page 66: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

fillchar(cx,sizeof(cx),true); tg := 0; count:=0; max:=0;end;{----------------------------------------------------------}procedure Try(i: integer);var j: integer;begin for j:=1 to n do begin if cx[j] then begin x[i]:=j; cx[j]:=false; tg := tg + p[j]; if (tg <= d[j]) then inc(count); if (i = n) then begin if count>max then begin max:=count; kqx:=x; end; end else if count+n-i>max then Try(i+1); if tg <= d[j] then dec(count); tg := tg - p[j]; cx[j]:=true; end; end;end;{---------------------------------------------------------}procedure Result;var i: integer; j: integer;begin assign(f,fout);rewrite(f); writeln(f,max); for i:=1 to n do write(f,kqx[i],' '); close(f);end;{----------------------------------------------------------}

Duyệt các cấu hình tổ hợp và ứng dụng Trang 66

Page 67: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

BEGIN Init; Try(1); Result;END.

Bài 4 : Truyền tin

Người ta cần truyền n gói tin được đánh số từ 1 đến n từ một điểm phát đến một điểm thu. Để thực hiện việc truyền tin có thể sử dụng m đường truyền được đánh số từ 1 đến m. Biết rằng nếu truyền j gói tin theo đường truyền tin i thì chi phí phải trả là sij (sij là số nguyên dương, sij < 32767, i =1,2,..,m, j = 1,2,…,n).

Yêu cầu: Hãy xác định số lượng gói tin cần truyền theo mỗi đường truyền tin để việc truyền n gói tin được thực hiện với tổng chi phí phải trả là nhỏ nhất.

Dữ liệu: Vào từ file văn bản TTIN1.INP:

+ Dòng đầu tiên chứa hai số nguyên dương n và m (n,m < 100) .

+ Dòng thứ i trong số m dòng tiếp theo chứa n số nguyên dương s i1, si2, .., sin , i=1,2,…,m.

Kết quả: Đưa ra file văn bản TTIN1.OUT:

+ Dòng đầu tiên chứa S là tổng chi phí phải trả theo cách truyền tin tìm được.

+ Dòng thứ hai chứa m số nguyên không âm q1, q2, .. ,qm, trong đó qi là số gói tin cần truyền theo đường truyền tin i.

Ví dụ:

TTIN1.INP TTIN1.OUT

3 3

20 20 20

4 3 10

1 3 20

4

0 2 1

Bài 5 : Thuê máy

Một trung tâm có n máy tính (cấu hình giống nhau) dùng để cho thuê trong tháng (từ ngày 1 đến ngày 31), thời gian thuê tính theo đơn vị ngày. Đầu tháng, trung tâm nhận được yêu cầu của m khách hàng (đánh số từ 1 đến m), mỗi khách hàng cần thuê một máy trong một số ngày nào đấy thuộc tháng. Giả thiết rằng, đối với mỗi khách hàng, hoặc trung tâm từ chối, hoặc trung tâm đồng ý cho thuê theo đúng như yêu cầu của khách. Với mỗi ngày, gọi tần số sử dụng máy là số máy túnh được sử dụng trong

Duyệt các cấu hình tổ hợp và ứng dụng Trang 67

Page 68: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

ngày đó. Hãy lập một phương án cho thuê máy để tổng tần số sử dụng máy trong tháng là lớn nhất.

Dữ liệu: Vào từ file văn bản THUEMAY.INP gồm:

+ Dòng đầu ghi các giá trị n, m.

+ m dòng tiếp theo, theo thứ tự 1, 2,…,m, mỗi dòng ghi yêu cầu của một khách: bắt đầu là số ngày mà khách cần thuê, tiếp theo là các ngày trong tháng mà khách cần thuê. Các giá trị trên cùng một dòng ghi cách nhau ít nhất một dấu trắng.

Kết quả: Đưa ra file văn bản THUEMAY.OUT:

+ Dòng đầu ghi số khách được thuê.

+ Dòng tiếp theo ghi các số hiệu khách được thuê, các số hiệu này phân cách nhau ít nhất một dấu trắng.

+ Dòng cuối ghi tổng tần số sử dụng máy.

Hạn chế kích thước: số máy, số khách không vướt quá 30

Ví dụ: THUEMAY.INP THUEMAY.OUT3 105 1 3 4 6 71 12 3 63 2 4 56 1 2 3 4 5 62 2 35 1 3 4 6 75 2 4 5 6 74 1 2 4 5 3 3 5 6

6 1 2 6 8 9 1020

Bài 6 : Dãy số

Cho dãy số gồm n số nguyên dương a1, a2, …, an (n < 1000) và số nguyên dương k (k < 50).

Yêu cầu: Tìm dãy con nhiều phần tử nhất của dãy đã cho và có tổng các phần tử chia hết cho k.

Dữ liệu: Vào từ file văn bản DAYSO.INP gồm:

+ Dòng đầu tiên chứa hai số n, k được ghi cách nhau bởi ít nhất một dấu trắng.

+ Các dòng tiếp theo chứa các số a1, a2, … ,an được ghi cách nhau ít nhất một dấu trắng hoặc dấu xuống dòng.

Kết quả: Ghi ra file văn bản DAYSO.OUT

Duyệt các cấu hình tổ hợp và ứng dụng Trang 68

Page 69: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

+ Dòng đầu tiên ghi m là số phần tử của dãy con tìm được.

+ Các dòng tiếp theo ghi dãy m chỉ số các phần tử của dãy đã cho có mặt trong dãy con tìm được. Các chỉ số được ghi cách nhau ít nhất một dấu trắng hoặc xuống dòng.

Ví dụ:DAYCON.INP DAYCON.OUT10 32 3 5 79 6 12 711 15

9 1 3 2 4 56 7 10 8

* Phân tích thuật toán: Chia từng số hạng của dãy cho k để tìm số dư, tính tổng các số dư. Sau đó tính r := tổngdư mod k;

+ Nếu r = 0 thì kết luận lấy được cả dãy

+ Ngược lại: nếu tìm trong dãy có 1 số chia cho k dư r thì chỉ cần loại số đó và dãy cần tìm gồm n-1 số còn lại;

Nếu không rơi vào 2 trường hợp trên thì thì ta đi “tìm cách loại đi ít nhất các phần tử để tổng các số còn lại chia hết cho k”:

Trước hết ta đi tìm số lượng từng loại số dư: SLDU[i] = j nghĩa là các số chia cho k dư i có j số (i=0,1,2, …,k-1)

Mỗi cách loại các phần tử được xác định bởi 1 bộ: x[1], x[2], …, x[n], trong đó x[i]=j, nghĩa là các số chia cho k dư i cần loại đi j số sao cho tổng các số còn lại chia hết cho k.

Rõ ràng khi đi xây dựng các x[i] thì giá trị đề cử ở bước i sẽ là các số nguyên từ 0..SLDU[i].

Bài toán đưa về: Duyệt các cách loại phần tử (các bộ x[1], x[2], …, x[n], x[i] = 0..SLDU[i]), sau đó cập nhật kỷ lục để tìm ra 1 cách loại ít phần tử nhất. Kết quả của bài toán sẽ gồm các phần tử không bị loại, khi đó sẽ gồm nhiều phần tử nhất.

Như vậy, từ 1 bài toán tìm Max ta đã chuyển về 1 bài toán tìm Min có độ phức tạp nhỏ hơn (thời gian thực hiện nhanh hơn), đưa về việc giải 1 bài toán có kích thước nhỏ hơn, đơn giản hơn;

{Chương trình này có thể chạy nhanh với n=10000, k= 1000} program Dayso; uses crt; const fi = 'DAYCON.INP'; fo = 'DAYCON.OUT';

Duyệt các cấu hình tổ hợp và ứng dụng Trang 69

Page 70: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

maxn = 10000; maxk = 1000; type ksldu = array [0..maxk-1] of integer; kad = array [1..maxn ] of integer; kloai = array[1..maxn] of boolean; kx = array [1..maxk-1] of integer; var a : kad; du : kad;{du[i] = j nghia la phan tu thu i chia cho k duoc so du la j} sldu : ksldu;{sldu[i] = j so luong cac so chia cho k du i la bang j} loai : kloai; {danh dau cac chi so can loai bo} x,kqx : kx; n, k, d : integer; min, tongdu, r,tdloai, slloai : longint; f : Text; procedure nhap; var inp: text; i, t: integer; begin assign(f, fi); reset(f); readln(f, n, k); for i:=1 to n do read(f,a[i]); close(f); tongdu := 0; for i:=1 to n do begin du[i] := a[i] mod k; tongdu:= tongdu+du[i]; end; r := tongdu mod k; assign(f,fo); rewrite(f); end; procedure XetDacBiet; var i, j: integer; begin if r=0 then begin writeln(f,n); for i:=1 to n do begin write(f,i:6); if (i mod 100) = 0 then writeln(f); end; close(f);

Duyệt các cấu hình tổ hợp và ứng dụng Trang 70

Page 71: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

halt; end; for i:=1 to n do loai[i] := false; j :=0; for i:=1 to n do if du[i] = r then begin loai[i] := true; j := i; break; end; if j>0 then begin writeln(f,n-1); for i:=1 to n do if not loai[i] then begin write(f,i,' '); if (i mod 100) = 0then writeln(f); end; close(f); halt; end; end; procedure try(i: integer); var j : integer; begin for j:=0 to sldu[i] do begin x[i] := j; {nghĩa là: trong các số chia cho k dư i cần loại đi j số} slloai := slloai + j; {số lượng số cần loại đi} tdloai := tdloai + i*j; {tổng dư của các số loại đi} if i = k-1 then begin if (tdloai mod k = r) and (slloai < min) then begin min := slloai; kqx := x; end; end else if slloai < min then try(i+1); tdloai := tdloai - i*j; slloai := slloai - j; end; end; Procedure Tim; var i: integer;

Duyệt các cấu hình tổ hợp và ứng dụng Trang 71

Page 72: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Begin for i:=1 to k-1 do sldu[i] :=0; for i:=1 to n do sldu[du[i]] := sldu[du[i]] + 1; slloai := 0; tdloai := 0; min := maxlongint; try(1); for i:=1 to n do loai[i] := false; for i:=1 to n do if kqx[du[i]] <>0 then begin dec(kqx[du[i]]); loai[i] := true; end; writeln(f,n-min); for i:=1 to n do if not loai[i] then begin write(f,i,' '); if i mod 100 =0 then writeln(f); end; close(f); End; begin nhap; XetDacBiet; Tim; end.

Bài 7: Chia kẹo

Có N gói kẹo (N nguyên dương, N < 50), các gói kẹo được đánh số từ 1 đến N, gói kẹo thứ i có Ai cái kẹo (Ai nguyên dương và Ai < 20; i = 1, 2, 3, …, N).

Hãy tìm một cách chia các gói kẹo thành hai nhóm sao cho tổng số kẹo trong hai nhóm chênh lệch nhau ít nhất.

Dữ liệu: Nhập N và N số A1, A2, …, AN từ file văn bản KEO.INP có cấu trúc gồm 2 dòng: dòng đầu ghi số N, dòng thứ hai ghi các số lần lượt từ A1 đến AN. Các số bắt đầu ghi từ đầu dòng theo thứ tự từ trái sang phải.

Kết quả: Ghi ra tệp văn bản KEO.OUT gồm 3 dòng:

Dòng đầu tiên ghi 3 số X, Y, Z, trong đó X là số kẹo chênh lệch giữa hai nhóm, Y là số kẹo của nhóm 1, Z là số kẹo của nhóm 2;

Duyệt các cấu hình tổ hợp và ứng dụng Trang 72

Page 73: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Dòng thứ hai ghi số hiệu các gói kẹo của nhóm 1.

Dòng thứ ba ghi số hiệu các gói kẹo của nhóm 2.

Ví dụ:KEO.INP819 5 20 13 16 20 18 2

KEO.OUT1 56 573 5 6 1 2 4 7 8

Bài 8: Xếp hàng mua vé

Có N người xếp hàng mua vé. Ta đánh số họ từ 1 đến N theo thứ tự đứng trong hàng (từ đầu hàng đến cuối hàng). Thời gian phục vụ bán vé cho người thứ i là t i. Mỗi người cần mua một vé nhưng được quyền mua tối đa 2 vé, vì thế một số người có thể nhờ người đứng ngay trước mình mua hộ. Người thứ i nhận mua hộ vé cho người thứ i+1 thì thời gian mua vé cho 2 người là ri.

Yêu cầu: Tìm phương án sao cho N người đều có vé với thời gian ít nhất.

Dữ liệu: đọc từ file văn bản MUAVE.INP gồm có 3 dòng, dòng thứ nhất ghi số nguyên dương N, dòng thứ hai ghi N số t1, t2,…, tN, dòng thứ ba ghi N-1số r1, r2, …, rN-1.

Kết quả: ghi ra file văn bản MUAVE.OUT gồm: dòng thứ nhất là tổng thời gian phục vụ bán vé. Dòng tiếp theo ghi chỉ số của các khách hàng cần rời khỏi hàng

Ví dụ:

MUAVE.INP MUAVE.OUT

5

2 5 7 8 4

3 9 10 10

17

2 4

Bài 9: Tạo chuỗi kí tự

Cho 3 ký tự A, B, C và một số nguyên dương N ( 4 <=N<=100).

Yêu cầu: Từ 3 ký tự trên hãy viết chương trình tạo ra chuỗi ký tự thoả mãn các tính chất sau:

Có độ dài N.

Không có hai chuỗi con liên tiếp nào giống nhau.

Số ký tự B là ít nhất

Dữ liệu: Nhập số N từ file văn bản CHUOIKT.INP

Kết quả: Ghi ra file văn bản CHUOIKT.OUT có cấu trúc:

Duyệt các cấu hình tổ hợp và ứng dụng Trang 73

Page 74: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Dòng đầu ghi số ký tự B ít nhất trong chuỗi

Dòng 2 ghi chuỗi tìm được

Ví dụ:

CHUOIKT.INP CHUOIKT.OUT

10 2

ACABACBCAC

Bài 10: Các thanh gỗ

Ông Hoà Bình có một tập hợp các thanh gỗ có độ dài bằng nhau là L.

Ông chặt các thanh gỗ ra một cách ngẫu nhiên nhưng độ dài các mẩu con đều có độ dài nguyên.

Về sau ông Hoà Bình có ý định gắn các mẩu con để khôi phục lại các thanh gỗ ban đầu nhưng lại quên mất độ dài L. Ông đã quyết định tạo lập các thanh gỗ có độ dài bằng nhau.

Hãy giúp ông Hoà Bình tạo lập các thanh gỗ có độ dài như nhau và cành ngắn càng tốt.

Dữ liệu: vào cho từ file văn bản THANHGO.INP

Dòng đầu ghi số N (N <50), số lượng các mẩu gỗ

Trên mỗi dòng trong N dòng tiếp theo ghi Li (0 < Li < 100), là số nguyên, độ dài mẩu gỗ thứ i.

Kết quả: ghi ra file văn bản THANHGO.OUT

Dòng đầu ghi L là độ dài ngắn nhất tìm được

Trên mỗi dòng ghi độ dài các mẩu gỗ dùng để ghép thành thanh gỗ đó

* Ví dụ:THANHGO.INP THANHGO.OUT10235274613

92 3 45 3 17 26 3

Duyệt các cấu hình tổ hợp và ứng dụng Trang 74

Page 75: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

3

Bài 11: Trồng cây

Nhà Ông GĐ Sở văn hoá tỉnh BG có một đại sảnh rộng và đẹp. Ông có ý định trồng một số loại cây cảnh vào N chậu hoa đã được thiết kế cố định thành một hàng trên đại sảnh, các chậu hoa có số thứ tự từ 1 đến N tính từ trái sang phải. Biết được ý thích của Ông, các bạn bè đã mua tặng ông M cây cảnh khác nhau để trồng vào các chậu hoa nói trên. Mỗi cây cảnh có một số hiệu duy nhất trong khoảng từ 1 đến M. Ông muốn trồng các cây cảnh vào các chậu hoa theo thứ tự ràng buộc “nếu có cây cảnh số hiệu i và cây cảnh số hiệu j mà i<j thì cây cảnh số hiệu i sẽ được trồng bên trái cây cảnh số hiệu j”. Tất cả các cây cảnh đều được trồng vào các chậu hoa sao cho đảm bảo ràng buộc về thứ tự các số hiệu. Nếu số chậu hoa nhiều hơn số cây cảnh thì những chậu hoa không dùng tới sẽ để trống. Mỗi chậu hoa chỉ được trồng một cây cảnh.

Mỗi chậu hoa có thiết kế về hình dáng, kích thước, kiểu cách có thể khác nhau (các cây cảnh cũng có thể khác nhau). Vì thế, khi một cây cảnh i được trồng vào một chậu hoa j sẽ có một giá trị thẩm mỹ nhất định, giá trị này được biểu diễn bởi một số nguyên aij. Các chậu hoa để trống có giá trị bằng 0.

Yêu cầu: Hãy tìm cách trồng các cây cảnh vào các chậu hoa tuân theo ràng buộc về thứ tự sao cho tổng các giá trị thẩm mỹ là lớn nhất. Nếu có nhiều cách trồng có cùng giá trị thẩm mỹ thì chỉ cần đưa ra đúng một cách.

Dữ liệu: vào từ file văn bản TREE.INP gồm:

Dòng đầu tiên ghi 2 số M và N (1 < N < 100; M < N < 100).

M dòng tiếp theo, mỗi dòng ghi N số, dòng i ghi a[i,1],.., a[i,N] với -50<a[i,j]< 50 là già trị thẩm mỹ khi trồng cây cảnh i vào chậu hoa j.

Kết quả: ghi ra file văn bản TREE.OUT:

Dòng đầu tiên là tổng số thẩm mỹ của cách trồng.

Dòng thứ hai ghi M số, số thứ k ghi số hiệu của chậu hoa mà cây cảnh số hiệu k trồng vào.

Ví dụ:

TREE.INP TREE.OUT

35

7 23 -5 -24 16

5 21 -4 10

53

2 4 5

Duyệt các cấu hình tổ hợp và ứng dụng Trang 75

Page 76: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

23

-21 5 -4 -20 20

Bài 12 :Rôbốt quét vôi

Có 9 căn phòng (đánh số từ 1 đến 9) đã được quét vôi với mầu trắng, xanh hoặc vàng. Có 9 rôbốt (đánh số từ 1 đến 9) phụ trách việc quét vôi các phòng. Mỗi rôbốt chỉ quét vôi một số phòng nhất định. Việc quét vôi được thực hiện nhờ một chương trình cài sẵn theo qui tắc:

nếu phòng đang có màu trắng thì quét màu xanh,

nếu phòng đang có màu xanh thì quét màu vàng,

nếu phòng đang có màu vàng thì quét màu trắng,

Cần phải gọi lần lượt một số các rôbốt ra quét vôi (mỗi lần một rôbốt, một rôbốt có thể gọi nhiều lần và có thể có rôbốt không được gọi. Rôbốt được gọi sẽ quét vôi tất cả các phòng mà nó phụ trách) để cuối cùng các phòng đều có màu trắng.

Hãy tìn một phương án như vậy sao cho lượng vôi phải quét là ít nhất. Giả thiết rằng lượng vôi cho mỗi lượt quét đối với các phòng là như nhau.

Dữ liệu: vào từ fie văn bản ROBOTQV.INP gồm các dòng: 9 dòng đầu, mỗi dòng mô tả danh sách các phòng được quét vôi bởi một rôbốt theo thứ tự từ rôbốt 1 đến rôbốt 9. Mỗi dòng như vậy gồm các số hiệu phòng viết sát nhau. Chẳng hạn dòng thứ 2 có nội dung : 3578

Mô tả rôbốt 2 phụ trách việc quét vôi các phòng 3, 5, 7, 8.

Dòng cuối mô tả màu vôi ban đầu của các phòng. Dòng gồm 9 kí tự viết sát nhau, kí tự thứ i biểu diễn màu vôi của phòng i với qui ước: kí tự T chỉ màu trắng, kí tự X chỉ màu xanh, kí tự V chỉ màu vàng, .

Kết quả: ghi ra tệp văn bản ROBOTQV.OUT gồm một dòng dưới dạng:

Nếu không có phương án thì ghi một chữ số 0.

Trái lại ghi dãy thứ tự các rôbốt được gọi (các số hiệu rôbốt viết sát nhau)

Ví dụ:ROBOTQV.INP ROBOTQV.INP 1591233571475369456

2455688

Duyệt các cấu hình tổ hợp và ứng dụng Trang 76

Page 77: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

789258XVXVXVTXT

*Phân tích thuật toán

Mỗi phương án gọi Rôbốt là một chỉnh hợp lặp chập 9 của 3 phần tử {0,1,2}. Kí hiệu x = (x1, x2, ...,xn); với xi := j nghĩa là Rôbốt i được gọi j lần.

Gọi r[i] là xâu kí tự cho biết danh sách các phòng do Rôbốt i phụ trách

Khi đó giá của phương án x =

Bài 13: Xâu đối xứng

Xâu kí tự S được gọi là đố xứng nếu các ký tự cách đều đầu và cuối là giống nhau. Ví dụ ABA và abcba là những xâu đối xứng.

Xét các xâu có không quá 2000 kí tự, chỉ chứa các kí tự A..Z, a..z, 0..9. Hãy xoá đi ít kí tự nhất để thu được xâu đối xứng.

Dữ liệu: vào từ file văn bản XDX.INP

Dòng đầu tiên chứa số n biểu thị chiều dài xâu

Từ dòng thứ hai là n kí tự viết liền nhau, có thể trải trên nhiều dòng, mỗi dòng không quá 70 kí tự

Kết quả: Ghi ra tệp văn bản XDX.OUT chứa số m biểu thị số kí tự cần xoá

Ví dụ:

XDX.INP XDX.OUT

9

bbC1221bA

3

Bài 14: Xếp lịch 1

Cho N công việc, với mỗi công việc cho biết tiền công thu được khi thực hiện công việc này, thời gian để hoàn thành, thời điểm cuối cùng phải kết thúc. Hãy xếp lịch thực hiện sao cho thu được nhiều tiền công nhất.

Dữ liệu: Vào từ file văn bản XL1.INP gồm:

+ Dòng đầu là số nguyên dương N.

+ N dòng sau, dòng i+1 ghi 3 số tg, tdkt, gt tương ứng là thời gian cần thiết để hoàn thành, thời điểm bắt buộc phải xong, giá trị tiền công của công việc i, với (i=1,...,N);

Kết quả: Ghi ra file văn bản XL1.OUT như sau:

Duyệt các cấu hình tổ hợp và ứng dụng Trang 77

Page 78: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

+ Dòng đầu tiên là tổng giá trị tiền công;

+ Các dòng tiếp theo, mỗi dòng ghi 4 số: i, T1, T2, gt tương ứng là số hiệu công việc, thời điểm bắt đầu, thời điểm kết thúc, giá trị của công việc được chọn.

Ví dụ:XL1.I

NPXL1.OU

T101 4

895 5

864 11

835 7

841 2

253 11

616 11

614 7

283

10 15

14 71

3295 0 1

251 1 2

893 2 6

836 6 9

6110 9

14 71

Bài 15: Cho thuê máy tính

Tại thời điểm 0, ông chủ cho thuê máy tính nhận được đơn đặt hàng thuê sử dụng của N khách hàng. Các khách hàng được đánh số từ 1 đến N. Khách hàng i cần sử dụng máy từ thời điểm di đến thời điểm ci (di và ci là các số nguyên và 0 < di < ci < 1000000000), và sẽ trả tiền sử dụng máy là pi (pi nguyên, 0 < pi < 10000000);

Hãy xác định xem ông chủ cần nhận phục vụ những khách hàng nào sao cho khoảng thời gian sử dụng máy tính của hai khách hàng được nhận phục vụ bất kì không giao nhau và tổng tiền thu được từ phục vụ là lớn nhất.

Dữ liệu: vào từ file văn bản RENTING.INP. Dòng đầu tiên ghi số N (0 < N < 1000). Dòng thứ i trong N dòng tiếp theo ghi ba số di, ci, pi cách nhau bởi dấu trống, i=1,2,..,N.

Duyệt các cấu hình tổ hợp và ứng dụng Trang 78

Page 79: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Kết quả: ghi ra file văn bản RENTING.OUT. Dòng đầu tiên ghi hai số nguyên dương theo thứ tự là số lượng khách hàng nhận được phục vụ và tổng tiền thu được. Dòng tiếp theo ghi chỉ số của khách hàng được phục vụ.

Ví dụ:RENTING.INP

RENTING.OUT RENTING.INP

RENTING.OUT

3150 500 1501 200 100400 800 80

2 1802 3

4400 821 800200 513 500100 325 200600 900 600

2 11002 4

Bài 16: Xoay ô

Một diện tích được tạo bởi các ô vuông, gồm N hàng và N cột (các hàng được đánh số từ 1 đến N theo chiều từ trên xuống dưới và các cột được đánh số từ 1 đến N theo chiều từ trái sang phải). Mỗi ô vuông được chia đôi theo đường chéo: Một nửa màu đen, một nửa màu trắng. Trạng thái của mỗi ô vuông được mã hóa từ 0 đến 3 theo hình vẽ sau:

0 1 2 3

Một diện tích được xác định bởi trạng thái các ô vuông của nó. Có thể thay đổi trạng thái này bằng cách xoay các ô theo chiều kim đồng hồ một trong những góc 90, 180o, 270o.

Diện tích được gọi là hợp lệ nếu các phần cùng màu của các ô sát nhau không được có chung cạnh, chẳng hạn diện tích trong hình 1 là không hợp lệ, hình 2 là hợp lệ:

Hình 2 Hình 1

Hãy xác định xem diện tích đã cho đã hợp lệ chưa? Nếu chưa, cần tìm cách xoay lại một số ô cần thiết để diện tích là hợp lệ, sao cho số ô cần xoay là ít nhất.

Duyệt các cấu hình tổ hợp và ứng dụng Trang 79

Page 80: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

Dữ liệu vào cho trong file văn bản ROT.INF, dòng đầu là số N, tiếo theo là bảng N dòng, N cột ghi trạng thái của các ô tương ứng. Các giá trị trên cùng một dòng ghi cách nhau ít nhất một dấu trắng.

Lời giải đưa ra file văn bản ROT.INF, trong đó nếu diện tích đã cho là hợp lệ thì chỉ cần ghi một số 0, trái lại văn bản gồm dòng đầu tiên là số ô cần xoay, các dòng tiếp, mỗi dòng mỗi dòng mô tả một ô cần xoay bao gồm: tọa độ hàng, tọa độ cột và góc cần xoay theo chiều kim dồng hồ của ô (tính theo đơn vị độ - là một trong các giá trị 90, 180, 270). Các số này ghi cách nhau ít nhất một dấu trắng.

Thí dụ:ROT.INF (Hình 1)42 0 1 02 0 3 22 0 2 31 2 1 0

ROT.OUT61 1 2702 1 2702 3 1802 4 1803 2 2704 2 180

diện tích nhận được cho bởi hình 2.Giới hạn kích thước N 10.

Phân tích thuật toán

Văn bản chương trìnhProgram Xoayo;uses crt;const fi = 'ROT.INP'; fo = 'ROT.OUT'; otren:array[0..3,0..3] of integer = ((0,1,1,0),(0,1,1,0),(3,2,2,3),(3,2,2,3)); oduoi:array[0..3,0..3] of integer = ((0,0,3,3),(1,1,2,2),(1,1,2,2),(0,0,3,3)); maxn=10;var a,b,kqb:array[1..maxn,1..maxn]of integer; f:text; n,min,i:integer;Procedure init;var i,j:integer;Begin assign(f,fi); reset(f); readln(f,n); for i:=1 to n do for j:=1 to n do read(f,a[i,j]); b:=a; close(F); min:=n*n;

Duyệt các cấu hình tổ hợp và ứng dụng Trang 80

Page 81: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

End;procedure cnkl;var i,k,j,d:integer;begin d:=0; for i:=1 to n do for k:=i-1 downto 1 do begin b[k,i]:=otren[b[k,i-1],b[k+1,i]]; b[i,k]:=oduoi[b[i-1,k],b[i,k+1]]; end; for i:=1 to n do for j:=1 to n do if a[i,j]<>b[i,j] then Begin inc(d); if d > min then exit; End; if d < min then begin min:=d; kqb:=b; end;end;Procedure try(i:integer);var j:integer;begin for j:=0 to 3 do begin b[i,i]:=j; if i=n then cnkl else try(i+1); end;end;procedure viet;var i,j,doo:integer;begin assign(f,fo);rewrite(f); writeln(f,min); for i:=1 to n do for j:=1 to n do

Duyệt các cấu hình tổ hợp và ứng dụng Trang 81

Page 82: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

if a[i,j]<>kqb[i,j] then begin doo:=(kqb[i,j]-a[i,j])*90; if kqb[i,j]<a[i,j] then doo:=doo+360; writeln(f,i,' ',j,' ',doo); end; close(f);end;BEGIN init; try(1); viet;END.

Bài 17: Bìa đục lỗ

Có N phiếu đục lỗ hình vuông. Tren mỗi phiếu đục lỗ có K*K hình tròn được bố trí thành K hàng ngang, K hàng dọc, mỗi hàng K lỗ, sao cho tất cả các hình tròn được đục thủng thì vị trí các lỗ đục là trùng nhau khi xếp các phiếu này thành một chồng, cho dù có một số phiếu đã được xoay 90o, 180o, 270o.

Trên mỗi phiếu có mọtt số hình tròn được đục thủng.

Khi xếp các phiếu thành một chồng, các hình tròn ở cùng một vị trí tạo thành một cột.

Yêu cầu: Hãy chỉ ra một số ít nhất các phiếu cần xoay sao cho nếu xếp chúng thành một chồng thì trên mỗi cột đều có ít nhất một hình tròn được đục thục, hoặc cho biết điều này không thể thực hiện được.

Dữ liệu: Vào từ file văn bản BN4.INF:

- Dòng đầu là 2 số nguyên N, K (1N20, 2K10).

- Dòng thứ i trong N dòng tiếp theo chứa K*K số 0, 1 cho biết trạng thái các hình tròn của phiếu thứ i, liệt kê theo hàng ngang, từ trái sang phải và từ trên xuống dưới, trong đó số 1 (0) chỉ ra vị trí tương ứng là lỗ đục (không đục).

Các số trên 1 dòng cách nhau ít nhất một

Duyệt các cấu hình tổ hợp và ứng dụng Trang 82

Page 83: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

dấu cách.

Kết quả: Đưa ra file văn bản BL4.OUT:

- Dòng đầu tiên chứa số nguyên M là số phiếu cần xoay. M = -1 là không có cách xoay.

- Trong trường hợp M 0, thì dòng thứ 2 chứa N số nguyên R1, R2,…, RN, Ri bằng 0, 1, 2 hoặc 3, cho biết bìa thứ i cần xoay Ri*90o theo chiều kim đồng hồ.

- Nếu có nhiều cách chọn M phiếu để xoay thì chỉ cần nêu một trong số đó.Ví dụ:

BL4.INP BL4.OUT5 31 0 0 0 1 0 0 0 00 1 0 1 0 0 0 0 01 0 0 0 1 0 0 0 10 1 0 0 0 0 1 0 01 0 0 1 0 0 0 0 0

30 0 1 1 3

Chú ý: - Các file bài làm phải được đặt tên tương ứng là BL3.PAS và BL4.PAS.

Bài 18: Bầu cử

Bài 19: Chọn K số để tổng lớn nhất

Cho ma trận kích thước m.n gồm các số nguyên nằm trong khoảng 0..99.

Yêu cầu: Hãy chọn ra k số sao cho tổng các số được chọn là lớn nhất, biết rằng trên mỗi dòng, mỗi cột chọn nhiều nhất một số.

Dữ liệu: Vào từ file văn bản CHONK.INP có cấu trúc:

Dòng đầu ghi 3 số m, n, k. (1< k < m,n < 100)

M dòng tiếp theo, mỗi dòng ghi n số tương ứng với các giá trị trong ma trận

Kết quả: Ghi ra file văn bản CHONK.OUT có cấu trúc:

Dòng đầu tiên ghi tổng lớn nhất tìm được

K dòng tiếp theo, mỗi dòng ghi 3 số: số thứ nhất là giá trị của số tìm được, hai số sau là toạ độ [dòng, cột] của số được chọn.

Ví dụ:

CHONK.INP CHONK.OUT

5 4 4

12 9 7 17

72

19 4 1

Duyệt các cấu hình tổ hợp và ứng dụng Trang 83

Page 84: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

2 12 9 19

21 19 15 7

19 8 5 3

1 2 8 25

19 3 2

9 2 3

25 5 4

*Phân tích thuật toán:

Mỗi phương án của bài toán là một bộ có thứ tự gồm k thành phần: x = (x1, x2, …, xk), trong đó xi = (dòng i, cột i), dòng i = 1, 2, …, m và cột i = 1, 2, …, n; nếu i <> j thì xi <> xj ;

Vì dòng i có m khả năng lựa chọn và cột i có n khả năng lựa chọn nên bộ hai thành phần (xi, yi) có m*n khả năng lựa chọn.

Giá của mỗi phương án bằng f(x) =

“Bài toán đưa về: duyệt các chỉnh hợp không lặp chập k của m*n phần tử, tính giá của các phương án, só sánh giá của các phương án với nhau và giữ lại phương án có giá lớn nhất”

* Văn bản chương trình

Program chonKSoCotongLonNhat;uses crt;const fi = 'CHONK.INP'; fo = 'CHONK.OUT'; Maxmn = 100;var a: array[1..maxmn,1..maxmn] of byte; dong, cot, kqd, kqc : array[1..maxmn] of byte; cxd, cxc : array[1..maxmn] of boolean; m, n, k : byte; tmax, s : longint; procedure init; var f: text; i,j : integer; begin assign(f,fi); reset(f); readln(f,m,n,k); for i := 1 to m do

Duyệt các cấu hình tổ hợp và ứng dụng Trang 84

Page 85: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

for j:=1 to n do read(f,a[i,j]); close(f); fillchar(cxd, sizeof(cxd), true); fillchar(cxc, sizeof(cxc), true); s := 0; tmax := -maxint; end; procedure cnkl; var i,j : integer; begin if s > tmax then begin tmax := s; kqd := dong; kqc := cot; end; end; procedure inkq; var i,j : integer; f : text; begin assign(f,fo); rewrite(f); writeln(f,tmax); for i := 1 to k do writeln(f,a[kqd[i],kqc[i]],' ',kqd[i],' ',kqc[i]); close(f); end; procedure try(i:integer); var d,c : integer; begin for d := 1 to m do for c:=1 to n do begin if cxd[d] and cxc[c] then begin dong[i] := d; cot[i] := c;

s := s + a[d,c]; cxd[d] := false; cxc[c] := false; if i = k then cnkl else try(i+1); cxd[d] := true;

Duyệt các cấu hình tổ hợp và ứng dụng Trang 85

Page 86: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

cxc[c] := true;s := s - a[d,c];

end; end; end; BEGIN init; try(1); inkq; END.

Bài 20: Tìm tổng nhỏ nhất

Cho ma trận gồm m dòng, n cột có các phần tử là các số nguyên a[i,j], trong đó |a[i,j]|<30000 (i=1..m, j=1..n).

Yêu cầu: Hãy chọn trên mỗi dòng, mỗi cột của ma trận đúng một số sao cho không có hai số nào thuộc cùng một dòng hay cùng một cột để tổng các số được chọn là nhỏ nhất.

Dữ liệu: Vào từ file văn bản TONGMIN.INP có cấu trúc:

Dòng đầu ghi 2 số nguyên m, n. (1 < m < 100, 1 < n < 30);

Trong m dòng tiếp theo, dòng thứ i ghi n số a[i,j] với i=1..m, j=1..n;

Kết quả: Ghi ra file văn bản TONGMIN.OUT có cấu trúc:

Dòng đầu tiên ghi tổng nhỏ nhất tìm được

Trong n dòng tiếp theo, mỗi dòng ghi 3 số: số thứ nhất là giá trị của số được chọn, hai số sau là toạ độ [dòng, cột] của số được chọn.

Ví dụ:TONGMIN.INP TONGMIN.OUT7 4 8 6 -18 0-15 1 15 0-5 0 9 1311 -14 -12 1219 3 14 1220 -4 2 1710 -8 5 -20

-67-18 1 3-15 2 1-14 4 2-20 7 4

*Phân tích thuật toán:

* Nếu m < n thì : “duyệt các chỉnh hợp không lặp chập m của n phần tử {1,2,…,n}, tức là mỗi phương án cần tìm là một bộ x = (x1, x2, …, xm), xi = j nghĩa là

Duyệt các cấu hình tổ hợp và ứng dụng Trang 86

Page 87: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

chọn số ở hàng i cột j; i = 1, 2,.., m; j = 1,2, …,n; tính giá của phương án x bằng công

thức f(x) = và giữ lại phương án có giá trị nhỏ nhất”

* Nếu m > n thì : “duyệt các chỉnh hợp không lặp chập n của m phần tử {1,2,…,m}, tức là mỗi phương án cần tìm là một bộ x = (x1, x2, …, xn), xi = j nghĩa là chọn số ở cột i hàng j; i = 1, 2,.., n; j = 1,2, …,m; tính giá của phương án x bằng công

thức f(x) = và giữ lại phương án có giá trị nhỏ nhất”

Duyệt các cấu hình tổ hợp và ứng dụng Trang 87

Page 88: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

KẾT LUẬN

Hiện nay chưa có tài liệu chính thức dành cho lớp Chuyên Tin khối THPT. Mà chỉ tồn tại ở dưới dạng tên chuyên đề của Bộ Giáo dục gửi về cho các trường. Do vậy việc dạy và học gặp nhiều khó khăn trong việc thống nhất về nội dung cũng như mức độ về kiến thức chuyên môn. Nên việc nghiên cứu và xây dựng chuyên đề này là thực sự cần thiết.

Mục đích của chuyên đề là truyền tải một cách tổng quát, chi tiết và sự thống nhất về mặt nội dung để người đọc dễ hiểu và thấy được tầm quan trọng của bài toán liệt kê tổ hợp và một số bài tập ứng dụng trong Tin học dành cho học sinh chuyên tin ở trường THPT.

Nội dung của chuyên đề đã được các tác giả chọn lọc qua chương trình đã thực dạy tại trường và tham khảo của một số đồng nghiệp khác trong nước.

Kiến thức là vô hạn, trong chuyên đề này chúng tôi đã có gắng sáng tạo, sưu tầm và trao đổi một cách tốt nhất có thể về mặt lý thuyết, các bài tập ứng dụng và các bài tập trong các kỳ thi trong nước để tạo thành cuốn tài liệu hiệu quả dành cho giáo viên và các em học sinh đam mê tin học chính thức làm tài liệu cho mình trong quá trình học tập và nghiên cứu.

Duyệt các cấu hình tổ hợp và ứng dụng Trang 88

Page 89: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

TÀI LIỆU THAM KHẢO

[1]. Nguyễn Đức Nghĩa, Nguyễn Tô Thành. Toán rời rạc, NXB ĐHQGHN, 2003

[2]. ThS.Trần Đức Huyên. Phương pháp giải các bài toán trong Tin học. NXBGD. 2004

[3]. Nguyễn Xuân Huy. Sáng tạo trong thuật toán và lập trìng. NXBGD. 2007.

[4]. Lê Minh Hoàng. Giải thuật và lập trình – A.D.A DSAP Textbook, DHSPHN, 1999-2002. <Internet>

[5]. Trần Tuấn Minh. Thiết kế và đánh giá thuật toán. Đà lạt. <Internet>

[6]. Lê Minh Hoàng. Bài giảng các chuyên đề.[7]. PGS. TS. Bài tập lập trinh Turbo Pascal 7.0[8]. Robert Sedgewick. Cẩm nang thuật toán. tập 1,2. NXB Khoa học Kỹ thuật. Năm XB 1998.

Duyệt các cấu hình tổ hợp và ứng dụng Trang 89

Page 90: CHUYENDEDUYENCAUHINHTOHOP

THPT CHUYÊN BẮC GIANG

MỤC LỤC

MỞ ĐẦU...............................................................................................................................................1PHẦN 1. LÝ THUYẾT TỔ HỢP.........................................................................................................2

I. SƠ LƯỢC VỀ TỔ HỢP............................................................................................................21. Khái niệm..............................................................................................................................22. Các bài toán thường gặp........................................................................................................2

II. NHẮC LẠI LÝ THUYẾT TẬP HỢP.......................................................................................21. Các khái niệm và ký hiệu......................................................................................................22. Các phép toán trên tập hợp....................................................................................................3

III. CÁC NGUYÊN LÝ CƠ BẢN..............................................................................................31. Nguyên lí cộng......................................................................................................................32. Nguyên lí nhân......................................................................................................................43. Nguyên lí bù trừ....................................................................................................................64. Nguyên lí Dirichlê.................................................................................................................7

IV. MỘT SỐ CẤU HÌNH TỔ HỢP THƯỜNG GẶP.................................................................81. Hoán vị..................................................................................................................................82. Chỉnh hợp lặp chập k của n phần tử......................................................................................83. Chỉnh hợp không lặp chập k của n phần tử...........................................................................94. Tổ hợp k của n phần tử..........................................................................................................9

PHẦN 2. PHƯƠNG PHÁP SINH......................................................................................................12I. Khái niệm................................................................................................................................12II. Áp dụng phương pháp sinh vào giải một số bài toán..............................................................13

1. Bài toán 1: Liệt kê tất cả các dãy nhị phân có độ dài N......................................................132. Bài toán 2: Liệt kê các tập con m phần tử của tập n phần tử..............................................143. Bài toán 3: Liệt kê các hoán vị của tập n phần tử...............................................................174. Bài toán 4: Phân tích số nguyên dương N thành tổng các số nguyên không âm................19

PHẦN 3. GIẢI THUẬT QUAY LUI..................................................................................................231. Ý tưởng................................................................................................................................232. Thuật toán quay lui..............................................................................................................263. Các ví dụ.............................................................................................................................304. Tài liệu tham khảo...............................................................................................................49

PHẦN IV. ỨNG DỤNG.....................................................................................................................52I. KHÁI NIỆM BÀI TOÁN TỐI ƯU.........................................................................................52

1. Một số khái niệm.................................................................................................................522. Một số phương pháp giải bài toán tối ưu tổ hợp.................................................................55

II. PHƯƠNG PHÁP DUYỆT GIẢI BÀI TOÁN TỐI ƯU..........................................................561. Tư tưởng chủ đạo................................................................................................................562. Cấu trúc của phương pháp duyệt tổng quát.........................................................................56

III. BÀI TẬP ÁP DỤNG...........................................................................................................58KẾT LUẬN.........................................................................................................................................87TÀI LIỆU THAM KHẢO...................................................................................................................88MỤC LỤC...........................................................................................................................................89

Duyệt các cấu hình tổ hợp và ứng dụng Trang 90