Tải bản đầy đủ (.doc) (64 trang)

Báo cáo Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (2.65 MB, 64 trang )

"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

SỞ GIÁO DỤC VÀ ĐÀO TẠO HÀ TĨNH
TRƯỜNG THPT ĐỨC THỌ

“VẬN DỤNG THUẬT TOÁN TÌM KIẾM THEO CHIỀU RỘNG
TRÊN ĐỒ THỊ VÀO GIẢI HAI DẠNG BÀI TOÁN THƯỜNG GẶP
TRONG TIN HỌC”

Lĩnh vực/ Môn: Tin Học
Tên tác giả: Trần Văn Hòa
Giáo viên môn: Tin Học

NĂM HỌC: 2016 - 2017

Hà Tĩnh, tháng 11 năm 2016

Trường THPT Đức Thọ - Hà Tĩnh

1

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

A.

PHẦN MỞ ĐẦU

I. Lý do chọn đề tài


Phương pháp tìm kiếm theo chiều rộng trên đồ thị được mô phỏng giống như hình ảnh
vết dầu loang trên mặt nước. Thực tế ta thấy, nếu đổ một giọt dầu trên bề mặt nước thì vết
dầu đó sẽ loang ra theo không gian và thời gian. Nếu như mặt nước đủ lớn thì vết dầu đó sẽ
loang theo đường tròn tức là những điểm cùng khoảng cách so với tâm vết loang thì vết dầu
sẽ đến cùng một lúc. Đây cũng là điều khá thú vị, bất kể điểm nào trên mặt nước có liên
thông với tâm vết dầu thì sẽ loang đến đó. Do đó có thể sử dụng phương pháp này để kiểm
tra tính liên thông của bất kỳ điểm nào trong đồ thị.
Một ví dụ khá tương tự với vết dầu loang là hiện tượng giao động sóng cơ học trên
mặt nước. Một mặt nước phẳng lặng, nếu chúng ta ném một vật vào mặt nước thì trên mặt
nước sẽ xuất hiện các gợn sóng mà tâm sóng là điểm chúng ta ném xuống. Các gợn sóng
này sẽ dao động từ trong ra ngoài, với bán kính lớn dần. Với điều kiện tốt thì các gợn sóng
sẽ làm cả bề mặt nước đều phải dao động.
Phương pháp này có một số đặc điểm khá hay và thực tế:
* Những điểm có cùng khoảng cách so với tâm đường tròn thì sẽ được loang (dao
động) cùng một lúc.
* Những điểm mà vết dầu đi qua lần thứ nhất thì đường đi trong quá trình loang (dao
động) là đường đi ngắn nhất để đi từ tâm đến điểm đó.
* Những điểm có vết dầu loang đến là những điểm liên thông với nhau, hay là tồn tại
đường đi từ hai điểm bất kỳ trên bề mặt loang.
* Những điểm không có vết dầu loang đến thì không tồn tại đường đi đến những
điểm có vết dầu loang.
Hiện nay việc nghiên cứu, khai thác thuật toán tìm kiếm theo chiều rộng trên đồ thị hay
còn gọi là thuật toán “Loang” vào giải toán cũng được một số tác giả quan tâm nhưng chưa
có đề tài nào được công bố có tính chất hệ thống. Từ thực tiễn dạy học trong nhiều năm qua,
nhất là công tác bồi dưỡng học sinh giỏi, tôi đã áp dụng nhiều lần và đưa lại kết quả khả
quan. Với những lý do trên, tôi mạnh dạn chọn đề tài: "Vận dụng thuật toán tìm kiếm theo
chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học" làm đề tài
nghiên cứu. Hy vọng sẽ góp phần nâng cao chất lượng dạy học Tin học hiện nay ở trưởng
phổ thông.


Trường THPT Đức Thọ - Hà Tĩnh

2

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

II. Mục đích, nhiệm vụ của việc thực hiện đề tài nghiên cứu
Việc đưa ra các bài toán cùng phương pháp giải chúng bằng cách vận dụng một thuật
toán cụ thể là rất cần thiết nhằm giúp cho giáo viên, cũng như học sinh hệ thống lại các kiến
thức đã học đồng thời làm phong phú thêm tư duy thuật toán và lập trình của mình. Tôi xin
đưa ra mục đích, nhiệm vụ cụ thể của việc thực hiện đề tài:
- Giới thiệu về các khái niệm có liên quan trong quá trình thực hiện đề tài.
- Hệ thống các bài toán thường gặp theo mức độ từ đơn giản đến phức tạp với cách giải
đơn giản và dễ hiểu nhằm giúp cho giáo viên và học sinh bước đầu nhận dạng và giải một
số bài tập liên quan.
- Giới thiệu một số bài tập áp dụng.
Cấu trúc nội dung gồm:
Mục I. Cơ sở lý luận
Mục II. Hai dạng toán thường gặp.
Mục III. Bài tập đề nghị.
III. Đối tượng, thời gian và phương pháp nghiên cứu
1. Đối tượng nghiên cứu
Bài viết SKKN "Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai
dạng bài toán thường gặp trong Tin học" có đối tượng nghiên cứu là các bài toán "tìm
kiếm thành phần liên thông trên đồ thị" và các bài toán "tìm đường đi ngắn nhất (qua ít
đỉnh nhất)".
2. Thời gian nghiên cứu

SKKN được thực hiện trong năm học 2015 - 2016
3. Phương pháp nghiên cứu
Để hoàn thành SKKN này tôi sử dụng phối kết hợp nhiều phương pháp, trong đó
phương pháp chủ yếu là nghiên cứu tài liệu, tham khảo ý kiến của cấp trên và đồng nghiệp.
IV. Điểm mới trong kết quả nghiên cứu
Điểm mới trong kết quả nghiên cứu của đề tài được thể hiện qua hai khía cạnh sau:
- Thứ nhất: Đưa ra được hệ thống các bài tập theo các dạng, mức độ khác nhau và cách
cài đặt chương trình cũng được cải tiến dần từ mức dễ đến khó, từ đơn giản đến phức tạp.
Hơn nữa, từ việc hiểu rõ bản chất của phương pháp tìm kiếm theo chiều rộng trên đồ thị,
chúng ta có thể cài đặt thuật toán bằng các cấu trúc dữ liệu khác nhau vào từng bài toán cụ
thể nhằm tối ưu bộ nhớ cũng như thời gian tìm kiếm. Một số bài toán cần vận dụng thuật

Trường THPT Đức Thọ - Hà Tĩnh

3

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

toán một cách linh hoạt, có thể trong một chương trình phải sử dụng thuật toán nhiều lần
với các tùy chọn khác nhau…Hơn nữa nhiều lúc chúng ta cần phối hợp cả hai phương pháp
tìm kiếm (theo chiều rộng và chiều sâu) để nâng cao hiệu quả giải toán.
- Thứ hai: nhận diện được các bài toán cùng dạng hoặc tìm cách đưa chúng về cùng
dạng sao cho việc vận dụng phương pháp tìm kiếm theo chiều rộng trên đồ thị để giải sẽ
mang lại hiệu quả.

Trường THPT Đức Thọ - Hà Tĩnh


4

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

B. PHẦN NỘI DUNG
I. CƠ SỞ LÝ LUẬN
1. Một số khái niệm.
Định nghĩa 1: Đường đi có độ dài k (k nguyên dương) từ đỉnh u tới đỉnh v trên đồ thị
vô hướng G=(V, E) là dãy các đỉnh u=x 0, x1, x2, x3,…, xk=v mà các cạnh (xi, xi+1)∈E,
i=0,1,2,…,k-1. Đường đi này còn có thể biểu diễn dưới dạng dãy các cạnh: (x 0,x1), (x1,x2),
….,(xk-1,xk). Đỉnh u gọi là đỉnh đầu (xuất phát), đỉnh v gọi là đỉnh cuối (đỉnh đích) của
đường đi. Đường đi có đỉnh đầu trùng với đỉnh cuối gọi là một chu trình.
Đường đi hay chu trình được gọi là đơn nếu không có cạnh nào bị lặp lại.
Đường đi hay chu trình được gọi là cơ bản nếu không có đỉnh nào bị lặp lại (trừ trường
hợp trong chu trình thì đỉnh đầu trùng đỉnh cuối là được lặp lại)
Định nghĩa 2: Đường đi có độ dài k (k nguyên dương) từ đỉnh u tới đỉnh v trên đồ thị
có hướng G=(V, E) là dãy các đỉnh u=x0, x1, x2, x3,…, xk=v mà các cung (xi, xi+1)∈E,
i=0,1,2,…,k-1. Đường đi này còn có thể biểu diễn dưới dạng dãy các cung: (x 0, x1), (x1,x2),
….,(xk-1,xk). Đỉnh u gọi là đỉnh đầu (xuất phát), đỉnh v gọi là đỉnh cuối (đỉnh đích) của
đường đi. Đường đi có đỉnh đầu trùng với đỉnh cuối gọi là một chu trình (mạch vòng).
Định nghĩa 3: Đồ thị vô hướng G=(V,E) được gọi là liên thông nếu luôn tìm được
đường đi giữa 2 đỉnh bất kỳ của nó.
Định nghĩa 4: Cho đồ thị vô hướng G=(V,E) và đồ thị con của G là đồ thị G’=(V’,E’).
Đồ thị G’ được gọi là một vùng liên thông (hoặc thành phần liên thông) của G nếu:
+ G’ liên thông;
+ Không tồn tại đường đi nào từ một đỉnh thuộc G’ tới một đỉnh không thuộc G’ (nói
cách khác là bảo đảm tính tối đại của liên thông trong G’).

VD: Trong hình 5 xét 2 đồ thị G và H: G chỉ có một vùng liên thông duy nhất, H có ba
vùng liên thông là H1, H2, H3.
H2
G
H1

H
Hình 2: G liên thông, H gồm 3 vùng liên thông

H3

Định nghĩa 5: Đỉnh v được gọi là đỉnh khớp (đỉnh rẻ nhánh) của đồ thị vô hướng
G=(V,E) nếu khi loại bỏ đỉnh v và các cạnh liên thuộc với nó thì số thành phần liên thông
của G tăng thêm.

Trường THPT Đức Thọ - Hà Tĩnh

5

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

Cạnh e∈E được gọi là cầu nếu loại bỏ nó khỏi đồ thị G thì số thành phần liên thông của
G tăng thêm 1 đơn vị.
Định nghĩa 6: Đồ thị có hướng G=(V, E) được gọi là liên thông mạnh nếu với mọi cặp
đỉnh u và v luôn tồn tại hai đường đi: đường đi có hướng từ đỉnh u đến đỉnh v và đường đi
có hướng từ đỉnh v đến đỉnh u.
Định nghĩa 7: Queue (hàng đợi).

“Hàng đợi” là một cấu trúc dữ liệu quan trọng được áp dụng rất nhiều trong công nghệ
thông tin, khoa học và đời sống. Để dễ dàng hình dung về hàng đợi chúng ta có thể xem ví
dụ sau:
Trong một quầy bán vé ở sân bay, mọi người phải xếp hàng tuần tự để mua vé, đến lượt
hành khách nào thì hành khách đó mua vé và ra khỏi hàng, giả sử không có sự chen lấn.
Trong hàng đợi này có một số tính chất sau:

Hình 1: Minh họa hàng đợi mua vé.

* Người mua vé sẽ được thêm vào cuối hàng.
* Người đầu hàng sẽ bị xóa khỏi hàng khi thực hiện xong công việc mua vé.
Cấu trúc Hàng đợi được sử dụng trong bài nghiên cứu:
1. Hàng đợi là danh sách có thứ tự trong đó phép toán chèn luôn thực hiện ở một phía
gọi là phía sau (giống như cuối hàng trong mua vé). Còn phép toán xóa chỉ thực hiện ở phía
còn lại gọi là phía trước (giống như người mua vé xong thì ra khỏi hàng).
2. Thuật ngữ được dùng cho hai thao tác chèn và xóa đối với hàng đợi tương ứng là
enqueue (đưa vào) và dequeue (đưa ra). Và từ nay về sau, trong bài nghiên cứu khi tôi viết
là enqueue(u) thì được hiểu là thêm phần tử u vào hàng đợi, dequeue() được hiểu là xóa
phần tử đầu tiên của hàng đợi.

Trường THPT Đức Thọ - Hà Tĩnh

6

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

3. Các phần tử được lấy ra khỏi hàng đợi theo quy tắc FIFO “vào trước – ra trước”

(Fisrt In – First Out).
Minh họa cho thao tác trên hàng đợi:

Hình 2: Minh họa thao tác với hàng đợi.

Các hàm được sử dụng trong nghiên cứu:
4. enqueue(u)

: thêm phần tử u vào hàng đợi.

5. dequeue()

: lấy ra giá trị phần từ đầu tiên của hàng đợi, đồng thời xóa phần tử đó

ra khỏi hàng đợi.
• isEmpty()

: kiểm tra hàng đợi có rỗng hay không? (hàng đợi rỗng tức là số phần

tử có trong hàng đợi bằng 0).
2. Ý tưởng thuật toán tìm kiếm theo chiều rộng trên đồ thị.
Ý tưởng: Bắt đầu tìm kiếm từ một đỉnh v. Việc thăm đỉnh v sẽ phát sinh thứ tự duyệt
những đỉnh (x1, x2, x3,…,xp) kề với v (những đỉnh có cạnh nối trực tiếp với đỉnh v). Khi
thăm đỉnh x1 sẽ lại phát sinh yêu cầu duyệt những đỉnh (u 1, u2, u3,…,uq) kề với x1. Các đỉnh
u này “xa” v hơn những đỉnh x nên chúng sẽ được duyệt khi tất cả những đỉnh x đã duyệt
xong. Tức thứ tự duyệt đỉnh sau khi đã thăm x1 sẽ là: (x2, x3,…,xp, u1, u2, u3,…,uq).
Giả sử ta có một danh sách chứa những đỉnh đang "chờ" thăm. Tại mỗi bước, ta thăm
một đỉnh đầu danh sách và cho những đỉnh chưa "xếp hàng" kề với nó xếp hàng thêm vào
cuối danh sách. Chính vì nguyên tắc đó nên danh sách chứa những đỉnh đang chờ sẽ được tổ
chức dưới dạng hàng đợi (Queue – vào trước ra trước)

Một khái niệm tương đương: Đường đồng mức là đường nối các điểm có cùng giá trị
tìm kiếm. Nếu như trong thực tế lý tưởng thì đường đồng mức là đường tròn có tâm là điểm
bắt đầu tìm kiếm.
VD: Với đồ thị như hình 1, giử sử ta cho tìm kiếm từ đỉnh 1 thì sẽ được kết quả như
sau: 1 rồi đến 2, 3, 7, tiếp theo là 4, 5, và 6, 9, cuối cùng là 8

Trường THPT Đức Thọ - Hà Tĩnh

7

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"
1

2

Hình 1

3
4

7
6

5

9


8

Minh họa quá trình tìm kiếm:

2)

1)

4)

3)

5)

6)

7)

Trường THPT Đức Thọ - Hà Tĩnh

8)

8

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

9)


3. Hai hướng tìm kiếm.
Trong thực tế thuật toán tìm kiếm theo chiều rộng trên đồ thị được áp dụng theo một
trong hai trường hợp sau:
Thứ nhất: Tìm kiếm theo chiều rộng, tức là tìm kiếm theo bán kính. Những điểm có
cùng bán kính thì sẽ được xét cùng một lượt, điểm ở xa tâm nhất thì sẽ được xét đến cuối
cùng. Một ví dụ đặc trưng của trường hợp này là nếu như đổ một giọt dầu xuống nước thì
sau một thời gian nó sẽ lan ra cả bề mặt, những điểm gần tâm nhất sẽ được lan đến trước.
Dựa vào vết dầu này chúng ta có thể phát sinh thêm để giải bài toán kiểm tra tính liên thông
của đồ thị, đường đi ngắn nhất trong đồ thị, tìm đường đi tối ưu giữa hai hoặc nhiều đỉnh
bất kỳ.
Thứ hai: Tìm kiếm theo chiều sâu (tìm kiếm theo độ cao), nghĩa là những điểm có cùng
độ cao sẽ được thăm cùng một lượt (cơ bản cùng một lượt nhưng thực tế sẽ mất một khoảng
thời gian delta(t) nào đó để di chuyển nữa). Đặc trưng cụ thể của bài toán thể hiện qua ví dụ
sau: trong một thùng nước chúng ta bỏ vào đáy thùng những vật đặc có chiều cao khác nhau
chẳng hạn các viên đá có kích thước khác nhau. Nếu như chúng ta cho mực nước dâng lên
một cách từ từ chúng ta sẽ có một số nhận xét thực tiễn như sau: Những vật cản có chiều
cao thấp nhất sẽ bị tràn qua trước hay là sẽ bị ngập trước (với trường hợp không bị bao
quanh bởi các vật cản cao hơn), có một số trường hợp đặc biệt như có một vật nào đó có độ
cao thấp nhưng bị vây quanh bởi các vật có chiều cao cao hơn thì nước phải tràn qua các vật
ngoài rồi sau đó mới tràn vào trong. Một số bài toán có thể được áp dụng vào thực tiễn thì
sẽ dễ dàng giải quyết hơn.

Trường THPT Đức Thọ - Hà Tĩnh

9

Báo cáo sáng kiến năm học 2016 – 2017



"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

4. Thuật toán tìm kiếm theo chiều rộng trên đồ thị.
Thuật toán dưới đây được cài đặt bằng hàng đợi Queue:
Procedure BFS(v); {Tìm kiếm theo chiều rộng bắt đầu từ đỉnh v }
Begin
queue:=φ; {Queue xuất phát bằng rỗng}
enqueue(v); {nạp đỉnh v vào Queue}
Chuaxet[v] :=false ; {đánh dấu v đã xét}
While isEmpty() do {trong khi Queue khác rỗng:}
Begin
u=dequeue();{Lấy đỉnh u từ Queue ra, không chỉ lấy ra mà phải xóa nó ở trong
queue nữa, đồng thời trả về giá trị của phần tử lấy ra}
Thăm_đỉnh(u);
For y∈ Ke(u) do {duyệt các đỉnh kề với đỉnh u}
If chuaxet[y] then {nếu đỉnh y chưa xét đến}
Begin
enqueue(y) ; {nạp đỉnh y vào Queue}
Chuaxet[y]:=false; {đánh dấu đã xét}
End;
End;
End;
BEGIN
For v∈ V do Chuaxet[v]:=true; {Khởi tạo}
For v∈ V do
If Chuaxet[v] then BFS(v);
END.

Trường THPT Đức Thọ - Hà Tĩnh


10

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

II. HAI DẠNG BÀI TẬP THƯỜNG GẶP
1. Bài toán tìm thành phần liên thông của đồ thị.
1.1. Phương pháp chung.
Giả sử đồ thị vô hướng G=(V, E) có n đỉnh đánh số 1, 2, 3,…,n.
Để liệt kê các thành phần liên thông của G phương pháp cơ bản nhất là:
- Đánh dấu đỉnh 1 và những đỉnh có thể đến từ đỉnh 1, thông báo những đỉnh đó thuộc
thành phần liên thông thứ nhất.
- Nếu tất cả các đỉnh đều đã bị đánh dấu thì G là đồ thị liên thông, nếu không thì sẽ
tồn tại một đỉnh v nào đó chưa bị đánh dấu, ta sẽ đánh dấu v và các đỉnh có thể đến được
từ v, thông báo những đỉnh đó thuộc thành phần liên thông thứ 2
- Và cứ tiếp tục như vậy cho tới khi tất cả các đỉnh đều đã bị đánh dấu.
- Số lần gọi thực hiện thuật toán BFS cho ta tương ứng số thành phần liên thông của đồ
thị.
Thuật toán minh họa phương pháp trên:
Procedure BFS(u); { thuật toán “BFS” liệt kê và đánh dấu các đỉnh có thể đến được
từ u}
Begin

End;
BEGIN {chương trình chính}
Khởi tạo tất cả các đỉnh đều chưa đánh dấu (Sử dụng câu lệnh For – Do hoặc
fillchar)
dem:=0;

For u:=1 to n do
If <u chưa đánh dấu> then
Begin
dem:=dem+1;
Write(‘Thanh phan lien thong thu ’, dem, ‘ gom cac dinh:’);
BFS(u);
End;
END.

Trường THPT Đức Thọ - Hà Tĩnh

11

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

1.2. Một số ví dụ áp dụng
Ví dụ 1: Đếm nhóm bạn trong Hội trại (Trích đề thi chọn HSG lớp 12 Tỉnh Quãng
Bình năm học 2012 - 2013)
Trong một Hội trại hè do Tỉnh Đoàn tổ chức, có N học sinh tham gia, trong đó, có một
số học sinh quen nhau. Một số học sinh được gọi là cùng một nhóm bạn, nếu bất kì một học
sinh nào thuộc nhóm đều có quen ít nhất một học sinh khác trong cùng nhóm đó.
Yêu cầu: Hãy đếm xem có bao nhiêu nhóm bạn trong N học sinh tham gia Hội trại.
Dữ liệu vào: Cho trong file văn bản NHOMBAN.INP, có cấu trúc như sau:
- Dòng 1: Ghi số nguyên dương N, là số lượng học sinh tham gia Hội trại.
(1 ≤ N ≤ 1000).
- Trong N dòng tiếp theo: Mỗi dòng ghi N số nguyên dương a[i,j] với ý nghĩa:
a[i,j ] = 1 nếu học sinh i quen học sinh j (với i ≠j).

a[i,j] = 0 nếu học sinh i không quen học sinh j (với i ≠j).
a[i,i] = 1 (học sinh i được xem là quen bản thân nó).
Các số trên cùng một dòng được ghi cách nhau ít nhất một dấu cách.
Dữ liệu ra: Ghi ra file văn bản NHOMBAN.OUT, theo cấu trúc như sau:
- Dòng 1: Ghi số nguyên dương K, là số lượng nhóm bạn tìm được trong N học sinh
tham gia Hội trại.
Ví dụ:
NHOMBAN.INP
NHOMBAN.OUT
5
2
1 0 0 1 1
0 1 1 0 0
0 1 1 0 0
1 0 0 1 1
1 0 0 1 1
Ý tưởng giải thuật: Có thể giải bài toán theo nhiều cách. Cách giải sau đây áp dụng
thuật toán tìm kiếm theo chiều rộng trên đồ thị.
Với mỗi học sinh tham gia hội trại được biểu diễn tương ứng là một đỉnh của một đồ thị
vô hướng. Yêu cầu của bài toán được chuyển thành tìm số thành phần liên thông của đồ thị.
Giả sử ta đang tìm các bạn học sinh thuộc một nhóm bạn nào đó, ví dụ nhóm 1, lúc này
ta tiến hành tìm kiếm từ một học sinh x bất kỳ trong số N học sinh tham gia hội trại và đánh
dấu học sinh này là đã tham gia vào một nhóm 1. Từ học sinh x ta tìm và đánh dấu những
học sinh nào có quen với học sinh x và có quen nhau đưa vào nhóm 1.

Trường THPT Đức Thọ - Hà Tĩnh

12

Báo cáo sáng kiến năm học 2016 – 2017



"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

Nếu tất cả học sinh đều được đánh dấu thì kết luận có một nhóm bạn, ngược lại ta tiếp
tục tìm kiếm nhóm bạn khác bắt đầu từ một bạn học sinh chưa đánh dấu. Quá trình tìm
nhóm bạn kết thúc khi tất cả các học sinh đều được đánh dấu.
Số lần gọi thuật toán BFS cho biết số nhóm bạn cần tìm.
Chương trình tham khảo
Program Dem_nhom_ban_trong_hoi_trai;
Const fi= 'NHOMBAN.INP';
fo= 'NHOMBAN.OUT';
Var A:array[1..1000,1..1000] of 0..1;
Q:array[1..1000] of integer;
kt:array[1..1000] of boolean;
i,j,d,x,dem,n:integer;
f:text;
(*=====================================*)
Procedure doctep;
Begin
Assign(f,fi);reset(f);
readln(f,n);
for i:=1 to n do
begin
for j:=1 to n do read(f,a[i,j]);
readln(f);
end;
close(f);
Assign(f,fo);rewrite(f);
End;

(*=====================================*)
Procedure BFS(m:integer);
var dau,cuoi,x,y:Integer;
Begin
dau:=1;
cuoi:=1;
Q[cuoi]:=m;
kt[m]:=false;
while dau<=cuoi do
begin
x:=Q[dau];
inc(dau);
for y:=1 to n do
if ((A[y,x]=1) or (A[x,y]=1)) and (kt[y]) then
begin
inc(cuoi);
Q[cuoi]:=y;
kt[y]:=false;
end;
Trường THPT Đức Thọ - Hà Tĩnh

13

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

end;
End;

(*=====================================*)
Procedure xuli;
Var dem: integer;
Begin
fillchar(kt,sizeof(kt),true);
dem:=0;
for i:=1 to n do
if kt[i] then
Begin
dem:=dem+1;
BFS(i);
End;
Write(f,dem);
Close(f);
End;
(*=====================================*)
BEGIN
doctep;
xuli;
END.
Ví dụ 2: Đếm quần đảo (Trích đề thi HSG lớp 12 tỉnh Kiên Giang năm học 2011-2012)
Biển đông của nước ta có rất nhiều đảo chìm, đảo nổi. Để thuận tiện cho việc canh giữ
và quản lý các đảo, bộ đội Hải Quân đã đánh số hiệu các đảo từ 1..n, đồng thời xây dựng
đường đi qua lại giữa các đảo sao cho luôn có ít nhất một đường đi từ đảo này qua đảo kia
tạo thành một quần đảo (quần đảo là một hoặc nhiều đảo có đường đi nối nhau). Khi nước
thủy triều lên, xuống thì số lượng các đảo hoặc đường đi có thể giảm hoặc tăng. Tại đài
quan sát luôn có những số liệu tương ứng với thời điểm hiện tại của mực nước biển.
Yêu cầu: với một bộ số liệu tại một thời điểm, hãy giúp các chiến sĩ xác định có bao
nhiêu quần đảo tồn tại.
Dữ liệu: vào từ file văn bản QUANDAO.INP có cấu trúc như sau:

- Dòng đầu gồm 2 số nguyên n, m (n,m<=1000)
- m dòng tiếp theo, mỗi dòng 2 số nguyên chỉ 2 đảo có đường đi nối nhau
Các số trên cùng 1 dòng ghi cách nhau ít nhất 1 ký tự trắng.
Kết quả: Ghi ra file văn bản QUANDAO.OUT
Mỗi dòng là số hiệu các đảo của một quần đảo tìm được
Ví dụ :

Trường THPT Đức Thọ - Hà Tĩnh

14

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

QUANDAO.INP
12 9
13
14
15
24
67
68
9 10
9 11
11 12

QUANDAO.OUT
Quan dao thu 1 : 1, 2, 3, 4, 5

Quan dao thu 2 : 6, 7, 8
Quan dao thu 3 : 9, 10, 11, 12.

Ý tưởng giải thuật :
Ta xem mỗi đảo của quần đảo là một đỉnh của một đồ thị vô hướng. Khi đó đường đi
giữa đảo này đến đảo kia được kí hiệu bằng cạnh nối giữa đỉnh này và đỉnh kia của một đồ
thị. Bài toán được đưa về tìm số thành phần liên thông của đồ thị (tương ứng với tìm số
quần đảo đã tồn tại), mỗi thành phần liên thông gồm những đỉnh nào (tương ứng với mỗi
quần đảo gồm những đảo nào). Vận dụng thuật toán "tìm kiếm theo chiều rộng" trên đồ thị
vô hướng chúng ta sẽ giải quyết bài toán một cách dễ dàng.
Chương trình tham khảo như sau :
Var f:text;
a: array[1..1000,1..1000] of byte;
kt: array[1..1000] of boolean;
q: array[1..1000] of byte;
d, x, y, i, j, m, n, u, dau, cuoi:integer;
(*============================================*)
procedure nhap;
Begin
fillchar(a, sizeof(a),0);
fillchar(kt, sizeof(kt),true);
assign(f,' QUANDAO.INP');
reset(f);
readln(f,n,m); {xây dựng ma trận kề A từ tệp Dao.inp}
for i:=1 to m do
Begin
readln(f1,x,y);
a[x,y]:=1;
a[y,x]:=1;
End;

Close(f);
assign(f, 'QUANDAO.OUT');
rewrite(f);
for i:=1 to n do
Begin

Trường THPT Đức Thọ - Hà Tĩnh

15

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

for j:=1 to n do write(f, a[i,j],' ');
writeln(f);
End;
End;
(*============================================*)
Procedure BFS(t:integer); {Tìm kiếm theo chiều rộng trên đồ thị bắt đầu từ đỉnh t}
Begin
dau:=1;
cuoi:=1;
q[cuoi]:=t; kt[t]:=false;
while dau<=cuoi do
begin
u:=q[dau];
dau:=dau+1;
for i:=1 to n do

if (a[u,i]=1) and (kt[i]) then
begin
cuoi:=cuoi+1;
q[cuoi]:=i;
kt[i]:=false;
end;
end;
End;
(*============================================*)
Procedure xuli; {tìm số lượng quần đảo và các đảo của mỗi quần đảo}
var p,r:integer;
begin
d:=0;
for p:=1 to n do
if kt[p] then
begin
d:=d+1;
write(f, 'dao thu ', d, ' la ');
BFS(p);
for r:=1 to cuoi do write(f, q[r],' ');
writeln(f);
end;
writeln(f, d);
end;
(*============================================*)
BEGIN
nhap;
xuli;
close(f);
END.

Ví dụ 3: Bệnh SARS (Trích đề thi Olympic Tin học sinh viên lần thứ XII, 2003)

Trường THPT Đức Thọ - Hà Tĩnh

16

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

Một cơ quan có N nhân viên được đánh số thứ tự từ 1 đến N. Mỗi người có một phòng
làm việc riêng của mình. Do nhu cầu công việc, hàng ngày mỗi nhân viên có thể phải tiếp
xúc với một số nhân viên khác. Vào một ngày làm việc bình thường, có một nhân viên bị
nhiễm bệnh SARS, nhưng do không biết nên người này vẫn đi làm. Đến cuối ngày làm việc
người ta mới phát hiện ra người nhiễm bệnh SARS đầu tiên, Khả năng lây lan của SARS
rất nhanh chóng: một người nhiễm bệnh nếu tiếp xúc với một người khác có thể sẽ truyền
bệnh cho người này.
Yêu cầu
Hãy giúp các bác sỹ kiểm tra xem cuối ngày hôm đó, có tối đa bao nhiêu người có thể
sẽ nhiễm bệnh và đó là những người nào để còn cách ly. Người có tiếp xúc với người nhiễm
bệnh được coi là người nhiễm bệnh.
Dữ liệu:
Dữ liệu vào từ file văn bản SARS.INP.
Dòng đầu tiên ghi 2 số tự nhiên N và K (1< N ≤ 250, 1≤ K ≤ N) tương ứng là số lượng
người làm việc trong toà nhà và số hiệu của nhân viên đã nhiễm SARS đầu tiên.
Dòng thứ I trong N dòng tiếp theo ghi danh sách những người có tiếp xúc với người
thứ I theo cách sau: số đầu tiên J của dòng là tổng số nhân viên đã gặp người thứ I, tiếp
theo là J số tự nhiên lần lượt là số hiệu của các nhân viên đó. Nếu J = 0 có nghĩa rằng không
ai đã tiếp xúc với người thứ I.

Kết quả
Kết quả ghi ra file văn bản SARS.OUT như sau:
Dòng đầu tiên ghi số S là tổng số người có thể bị lây nhiễm SARS.
Dòng thứ 2 liệt kê tất cả các người có thể bị lây nhiễm SARS cần cách ly, danh
sách cần được đưa ra theo thứ tự của số hiệu nhân viên nhiễm bệnh.
Trong file dữ liệu vào và file kết quả, các số trên một dòng cách nhau ít nhất một dấu
cách.
Ví dụ:
SARS.INP
51
223
213
12
15
14

SARS.OUT
3
123

Ý tưởng giải thuật:
Với bài toán này chúng ta có thể giải theo nhiều cách khác nhau. Tuy nhiên cách giải sử
dụng thuật toán "BFS" trên đồ thị tỏ ra hiệu quả và dễ hiểu hơn so với các cách giải khác.

Trường THPT Đức Thọ - Hà Tĩnh

17

Báo cáo sáng kiến năm học 2016 – 2017



"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

- Chúng ta xem mỗi nhân viên của cơ quan là một đỉnh của một đồ thị vô hướng. Lúc
này ta quy ước hai đỉnh i và j được gọi là có đường nối nếu như hai nhân viên i và j có tiếp
xúc với nhau.
- Áp dụng thuật toán "BFS" xuất phát từ đỉnh k (người đầu tiên bị nhiễm bệnh). Tiến
hành duyệt và đánh dấu đã duyệt bắt đầu từ đỉnh k, tìm đến đâu đếm và đánh dấu số nhân
viên bị lây nhiễm đến đó đồng thời lưu nhân viên đó vào mảng b. Sau khi duyệt hết các đỉnh
liên thông với k (người có tiếp xúc với người nhiễm bệnh bắt đầu từ người thứ k) chúng ta
sẽ tìm ra được tổng số người tối đa nhiễm bệnh và tên từng người đó.
Chương trình tham khảo như sau:
Var f,g:text;
a:array[1..250,1..250] of byte;
kt:array[1..250] of boolean;
q,b:array[1..250] of integer;
d,x,y,i,j,m,n,u,dau,cuoi,k:integer;
(*============================================*)
Procedure Nhap; {xây dựng ma trạn kề A từ tệp vào Sars.inp, lưu ý cách đọc tệp}
Begin
Fillchar(a,sizeof(a),0);
Fillchar(kt,sizeof(kt),true);
Assign(f, 'sars.inp');reset(f);
Assign(g, 'sars.out');rewrite(g);
Readln(f,n,k);
For i:=1 to n do
Begin
Read(f,x);
For j:=1 to x do
Begin

read(f,y);
a[i,y]:=1;
a[y,i]:=1;
End;
Readln(f);
End;
End;
(*============================================*)
Procedure BFS(t:integer); {Tìm kiếm bắt đầu từ đỉnh t}
Begin
dau:=1;
cuoi:=1; d:=1;
q[cuoi]:=t; b[d]:=t;kt[t]:=false;
while dau<=cuoi do
Begin
u:=q[dau];
dau:=dau+1;
for i:=1 to n do
Trường THPT Đức Thọ - Hà Tĩnh

18

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

if (a[u,i]=1) and (kt[i])then
Begin
cuoi:=cuoi+1;

d:=d+1;
b[d]:=i;
q[cuoi]:=i;
kt[i]:=false;
End;
End;
End;
(*============================================*)
Procedure Xuli;
Begin
BFS(k); {tìm kiếm số người nhiễm bệnh bắt đầu từ người k nhiễm bệnh đầu tiên}
writeln(g, d); {số người tối đa nhiễm bệnh}
For i:=1 to d do write(g, b[i],' '); {danh sách những người nhiễm bệnh}
End;
BEGIN
Nhap;
Xuli;
Close(f);
Close(g);
END.
Ví dụ 4 : Truyền tin trên mạng
Có một nhóm N học sinh, đánh số từ 1 đến N, một số người trong họ có thể liên lạc
được với nhau qua email (1 chiều). Khi biết một thông tin mới họ dùng email gửi thông tin
đó cho nhau. Thầy giáo chủ nhiệm biết email của mọi bạn, và có một thông tin đặc biệt
muốn gửi cho tất cả N học sinh này. Hãy tìm số ít nhất học sinh mà thầy giáo sẽ gửi email
cho họ để họ truyền tin cho mọi người còn lại.
Dữ liệu vào cho ở file văn bản INFOR.INP :
- Dòng đầu là số N (N<=1000).
- N dòng tiếp theo, dòng thứ i trong N dòng này chứa
danh sách các học sinh mà học sinh thứ i có thể gửi email

cho họ. Nếu danh sách rỗng thì dòng này bỏ trống.

INFOR.IN
P
6
2 3
1
1
5
4

INFOR.OUT
3
1
4
6

Kết quả ghi ra file văn bản INFOR.OUT :
- Dòng đầu ghi số k là số người ít nhất nhận thông tin trực
tiếp từ Thầy giáo.
- Dòng thứ hai ghi số hiệu của K người đó.
Ý tưởng giải thuật: Bài toán được quy về tìm các thành phần liên thông trên đồ thị.
Với mỗi thành phần liên thông, xuất ra 1 đỉnh tùy ý.
Chương trình tham khảo :
Trường THPT Đức Thọ - Hà Tĩnh

19

Báo cáo sáng kiến năm học 2016 – 2017



"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

Program TRUYEN_TIN;
Var f:text;
a:array[1..1000,1..1000] of 0..1;
b:array[1..1000] of integer;
kt:array[1..1000]of boolean;
q:array[1..1000] of byte;
d,x,y,i,j,m,n,u,dau,cuoi:integer;
(*===========================*)
Procedure nhap;
Begin
fillchar(a,sizeof(a),0);
fillchar(kt,sizeof(kt),true);
Assign(f, 'infor.inp');
Reset(f);
Readln(f,n);
While not eof(f) do
Begin
while not eoln(f) do
Begin
read(f,x);
a[i,x]:=1;
End;
Readln(f);
End;
Close(f);
Assign(f,'infor.out');
Rewrite(f);

End;
(*===========================*)
Procedure BFS(t:integer);
Begin
dau:=1;
cuoi:=1;
q[cuoi]:=t; kt[t]:=false;
While dau<=cuoi do
Begin
u:=q[dau];
dau:=dau+1;
For i:=1 to n do
if (a[u,i]=1)and(kt[i])then
Begin
cuoi:=cuoi+1;
q[cuoi]:=i;
kt[i]:=false;
End;
End;
End;
(*===========================*)

Trường THPT Đức Thọ - Hà Tĩnh

20

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"


Procedure xuli;
Var p,r:integer;
Begin
d:=0;
For p:=1 to n do
If kt[p] then
Begin
d:=d+1;
BFS(p);
b[d]:=p;
End;
writeln(f,d);
For i:=1 to d do writeln(f, b[i]);
End;
(*===========================*)
BEGIN
Nhap;
Xuli;
Close(f);
END.
Ví dụ 5: Miền liên thông.
Cho bảng chữ nhật chia thành M xN ô vuông đơn vị (M dòng đánh số từ 1 đến M theo
chiều từ trên xuống dưới, N cột đánh số từ 1 đến N theo chiều từ trái qua phải. Mỗi ô vuông
ghi 1 số 0 hoặc 1. Một miền 0 của bảng là tập hợp các ô chung cạnh và chứa số 0). Địa chỉ
của một miền là toạ độ [dòng, cột] của ô đầu tiên thuộc miền theo thứ tự duyệt từ trái qua
phải, từ trên xuống dưới. Hãy tìm số miền 0 của bảng và tìm miền 0 có diện tích lớn nhất
(có nhiều ô nhất).
Dữ liệu vào : File Mien.INP có cấu trúc :
Dòng đầu ghi 2 số nguyên dương M và N (0

M dòng tiếp theo thể hiện bảng số theo thứ tự từ trên xuống dưới, mỗi dòng N số theo
thứ tự từ trái sang phải.
Dữ liệu ra : File Mien.Out có cấu trúc :
Dòng thứ nhất ghi số lượng miền 0.
Dòng thứ 2 ghi diện tích của miền 0 có diện tích lớn nhất.
Các dòng tiếp theo, mỗi dòng ghi địa chỉ một miền 0 có diện tích lớn nhất.
Ý tưởng giải thuật : Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị:


Thực hiện vòng lặp.

1. Tìm một ô chứa số 0 chưa thăm là ô x có toạ độ dòng và cột là (i,j).
2. Thực hiện thuật toán " BFS" để tìm được miền 0 chứa ô x. Trong quá trình tìm kiếm
cũng tính diện tích của miền (mỗi lần đến một ô mới thì tăng diện tích lên một đơn vị).

Trường THPT Đức Thọ - Hà Tĩnh

21

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

3. Mỗi lần thực hiện xong thuật toán "BFS" thì tìm được một miền 0 chứa ô (i,j), lưu
kết quả (toạ độ i, j và diện tích của miền vào mảng KQ) đồng thời tăng biến đếm số miền 0.
• Hiện số lượng miền 0.
• Duyệt mảng KQ để tìm miền 0 có diện tích lớn nhất. Hiện diện tích miền 0 lớn nhất
• Duyệt mảng KQ lần thứ 2 để hiện toạ độ từng ô đại diện cho mỗi miền 0 có diện tích
bằng diện tích của miền lớn nhất.

Chương trình tham khảo :
Program Mien_lien_thong ;
const hx:array[1..4] of integer=(-1,0,1,0);
hy:array[1..4] of integer=(0,-1,0,1);
Type banghi=record
h,c:integer;
end;
var a:array[0..100,0..100] of 0..1;
q:array[1..100] of banghi;
kq:array[1..2] of banghi;
r,x,y,dau,cuoi,i,j,m,n,d,somien,u,v,max:integer;
dd:array[1..100,1..100] of boolean;
f:text;
(*==============================*)
Procedure doctep;
begin
fillchar(a,sizeof(a),1);
assign(f,'MIENLIENTHONG.INP');reset(f);
readln(f,m,n);
for i:=1 to m do
begin
for j:=1 to n do read(f,a[i,j]);
readln(f);
end;
for i:=1 to m do
begin
for j:=1 to n do write(a[i,j],' ');
writeln;
end;
close(f);

end;
(*==============================*)
Procedure BFS(k,l:integer); {Tìm kiếm bắt đầu từ ô có tọa độ (k,l)}
begin
dau:=1;
cuoi:=1;
q[cuoi].h:=k;
q[cuoi].c:=l;
dd[k,l]:=false;
d:=1;

Trường THPT Đức Thọ - Hà Tĩnh

22

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

while dau<=cuoi do
begin
x:=q[dau].h;
y:=q[dau].c;
dau:=dau+1;
for r:=1 to 4 do
begin
u:=x+hx[r];
v:=y+hy[r];
if (a[u,v]=0) and (dd[u,v]) then

begin
cuoi:=cuoi+1;
q[cuoi].h:=u;
q[cuoi].c:=v;
d:=d+1;
dd[u,v]:=false;
end;
end;
end;
end;
(*==============================*)
Procedure xuli;
begin
max:=0; somien:=0;
fillchar(dd,sizeof(dd),true);
fillchar(kq,sizeof(kq),0);
assign(f,'MIENLIENTHONG.OUT');rewrite(f);
for i:=1 to m do
for j:=1 to n do
if (a[i,j]=0) and (dd[i,j]) then
begin
somien:=somien+1;
BFS(i,j);
if d>max then
begin
max:=d;
kq[1].h:=i;
kq[1].c:=j;
kq[2].h:=x;
kq[2].c:=y;

end;
end;
writeln(f, somien);
writeln(f,max);
writeln(f,kq[1].h,' ',kq[1].c);
write(f,kq[2].h,' ',kq[2].c);
close(f);
end;

Trường THPT Đức Thọ - Hà Tĩnh

23

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

(*==============================*)
BEGIN
doctep;
xuli;
END.
Ví dụ 6: Sói và cừu
Có một số con cừu trong trại chăn nuôi của Mickey. Trong khi Mickey đang ngủ say,
những con sói đói đã vào trại và tấn công đàn cừu.
Trại có dạng hình chữ nhật gồm các ô tổ chức thành hàng và cột. Kí tự dấu chấm ‘.’ là ô
rỗng, kí tự ‘#’ là hàng rào, kí tự ‘o’ là cừu và kí tự ‘v’ là chó sói.
Chúng ta coi 2 ô là cùng một miền nếu có thể chuyển từ ô nọ tới ô kia bằng đường đi
chỉ gồm các đường đi theo chiều ngang hoặc thẳng đứng không vướng hàng rào. Các ô mà

từ chúng có thể thoát khỏi sân không được xem là một phần của bất kì miền nào.
May thay, những con cừu biết tự vệ. Chúng có thể chiến đấu với những con sói trong
miền (húc chết sói) nếu số lượng cừu lớn hơn số lượng sói trong cùng một miền. Ngược lại
những con sói sẽ ăn hết các con cừu trong cùng một miền.
Ban đầu các con cừu và các con sói đã được xác định trong các miền của trại.
Viết một chương trình tính số lượng cừu và số lượng sói còn lại trong sáng hôm đó.
Dữ liệu vào: File văn bản SOICUU.INP:
Dòng đầu tiên chứa 2 số nguyên R và C (3<=R,C<=250) là số hàng và số cột của trại.
Mỗi dòng trong R dòng sau gồm C kí tự. Tất cả các kí tự này biểu diễn các vị trí có
hàng rào, cừu và chó sói trong trại.
Kết quả: Ghi ra file SOICUU.OUT chỉ một dòng gồm 2 con số: Số cừu và số sói còn
lại trong trại.
Ví dụ:
SOICUU.INP

SOICUU.INP

6 6
...#..
.##v#.
#v.#.#
#.o#.#
.###.#
...###

8 8
.######.
#..o...#
#.####.#
#.#v.#.#

#.#.o#o#
#o.##..#
#.v..v.#
.######.

SOICUU.OUT
0 2

SOICUU.OUT
3 1

Trường THPT Đức Thọ - Hà Tĩnh

24

Báo cáo sáng kiến năm học 2016 – 2017


"Vận dụng thuật toán tìm kiếm theo chiều rộng trên đồ thị vào giải hai dạng bài toán thường gặp trong Tin học"

Ý tưởng giải thuật : Sử dụng thuật toán "BFS" tìm kiếm các miền liên thông. Trong
mỗi miền liên thông đếm số cừu và số sói trong đó. Nếu số cừu lớn hơn số sói thì coi như số
sói còn lại trong miền này bằng 0, nếu ngược lại thì số cừu còn lại trong miền này bằng 0.
Khi tìm tới ô nào thì xoá ô đó bằng cách gán kí tự ‘#’ trên ô đó.

Trường THPT Đức Thọ - Hà Tĩnh

25

Báo cáo sáng kiến năm học 2016 – 2017



×