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

Thuat toan lui

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 (303.67 KB, 16 trang )

<span class='text_page_counter'>(1)</span><div class='page_container' data-page=1>

<b>Lê Sỹ Hùng(Sưu Tầm) Hương Sơn Hà Tĩnh</b>



<i>Một bài toán liệt kê tổ hợp ln cần phải đảm bảo hai nguntắc, đó là: khơng được bỏ </i>
<i>sót một cấu hình và khơng được trùnglặp một cấu hình. Có thể nói rằng phương pháp liệt</i>
<i>kê là cách cuốicùng để có thể giải được một số bài toán tổ hợp hiện nay. Mộttrong những</i>
<i>phương pháp liệt kê có tính phổ dụng cao đó là phươngpháp quay lui. </i>


Nội dung chính của phương pháp này là việc xây dựng dần cácthành phần của cấu hình
bằng cách thử tất cả các khả năng. Giả thiếtcấu hình cần được tìm được mơ tả bằng một
bộ giá trị (x 1 ,x 2 ,..,x N ).Giả sử đã xác định được i - 1 thành phần (x 1 ,x 2 ,...,x i-1 ),bây giờ


ta xác định thành phần x i bằng cách duyệt tất cảcác khả năng có thể đề cử cho nó (đánh


số từ 1 đến n i ).Với mỗi khả năng j, kiểm tra xem j có được chấp nhận hay khơng. Cóthể


có hai trường hợp có thể xảy ra:


- Nếu j được chấp nhận thì xác định x i theo j, sau đó nếu j = N thì ta được một cấu


hình,trái lại ta tiếptục tiến hành việc xác định x i+1 .


- Nếu thử tất cảcác khả năng mà mà khơng có khả năng nào được chấp nhận thì ta sẽlùi
lại bước trướcđể xác định x i-1 .


Thơng thường ta phân tích q trình tìm kiếm thành cây tìm kiếm.Khơng gian tìm kiếm
càng lớn hay càng nhiều khả năng tìm kiếm thì câytìm kiếm càng lớn, càng nhiều nhánh.
Vì vậy hạn chế và bỏ bớt cácnhánh vơ nghiệm của cây tìm kiếm thì sẽ tiết kiệm được thời
gianvà bộ nhớ, tránh bị tràn dữ liệu. Q trình tìm kiếm lời giải theothuật tốn quay lui có
thể được mơ tả bởi mơ hình cây tìm dướiđây:


Cần phải lưu ý là ta phải ghi nhớ tại mỗi bước đã đi qua,những khả năng nào đã thử để


tránh trùng lặp. Những thông tin nàyđược lưu trữ theo kiểu dữ liệu ngăn xếp - Stack ( vào
<i>sau ra trước) - vì thế nên thuật tốn này phù hợp thểhiện bởi thủ tục đệ quy. Ta có thể mô</i>
tả bước xác định x i bởi thủ tục đệ quy sau:


Procedure Try (i: integer);
Var j : integer;


Begin


For j:= 1to ni do


</div>
<span class='text_page_counter'>(2)</span><div class='page_container' data-page=2>

(xác định xi theo j )


if i = N then (ghi nhận một cấu hình)
else try(i+1);


End;
End;


Trong thủ tục mô tả trên, điều quan trọng nhất là đưa rađược một danh sách các khả
năngđề cử và xác định được giá trịcủa biểu thức logic [ chấp nhận j ]. Ngoài việc phụ
thuộc j, giá trị này còn phụ thuộc vào việc đã chọn các khả năng tại i - 1bước trước đó.
Trong những trường hợp như vậy, cần ghi nhớ trạng thái mới của quá trìnhsau khi [xác
định xi theo j ] vàtrả lại trạng thái cũ sau lời gọi Try(i+1).Các trạng thái này được ghi


nhận nhờ một số biến tổng thể(global), gọi là các biến trạng thái.


Dễ thấy rằng bài tốn vơ nghiệm khi ta đã duyệt hết mọi khảnăng mà khơng có khả năng
nào thoả mãn u cầu. Ta nói rằng là đã vét cạn mọi trường hợp.Chú ý rằng là đến một
lúc nào đó ta phải lùi liên tiếp nhiều lần.Từ đó suy ra rằng, thơng thường bài tốn vơ


nghiệm khi khơng thể lùiđược nữa. Thuật tốn này sẽ khơng có tính khả thi cao bởi dùng
thủtục đệ quy dễ bị lỗi tràn Stack.


<b>Bài 1: Hành trình ký tự</b> Cho tệp văn bản HT_KITU.INP chứa các dịng ký tự chiều dài
khơngq 32. Hãy lập trình thực hiện các cơng việc sau: Lần lượt đọc cácdịng vào một
xâu, sau đó từ xâu xây dựng lưới ơ vng dạng tam giácnhư sau: ví dụ xâu =’Vinh’, lưới
ơ vng có dạng như hình 1. Xuấtphát từ ơ góc trên trái (chữ V), đi theo các hướng có thể
để xâydựng lại xâu đã cho. Với mỗi hành trình thành cơng hãy in ra số thứtự của hành
trình và chỉ ra hành trình trên lưới, mỗi ký tự của hànhtrình thay bằng một dấu ’*’.
<b>Ví dụ: </b>


Sau mỗi lời giải phải ấn ENTER để in lời giải tiếp.
<b>Hướngdẫn giải </b>


Tổ chức hai mảng hai chiều F, Kt[1..32,1..32] of Char.Mảng Kt dùngđể tạo ra ma trận kí
tự dạng tam giác như trên gồm các kí tự từ xâuS đọc từ file dữ liệu. Mảng F dùng để ghi
nhận các hành trình thànhcơng, nếu ơ (i,j) thuộc hành trình thì F[i,j] = ’*’.


Sau khi xây dựng xong ma trận kí tự, ta dùng thủ tục đệ quy Try(i,j,h: byte) để tìm tất cả
các hành trình. Giả sử ta đangở ơ (i,j) nào đó trên hành trình và đã được một xâu kí tự độ
dài h ≤ length(S ). Nếu h = length(S )thì ta đã được một hành trình và ta sẽ ghi nhận nó,
in ra màn hìnhhành trình đó. Cịn nếu h < length(S )thì từ ơ (i,j) tasẽ có thể đi theo hai
hướng đó là đến ơ (i,j+1) hoặclà ơ (i+1,j). Từmỗi ơ đó ta lại tiếp tục đến các ơ khác để
tìm hành trình. Qtrình đó được tiếp tục thựchiện các ơ đó cho đến khi duyệt được hết
nghiệm của bài toán.


</div>
<span class='text_page_counter'>(3)</span><div class='page_container' data-page=3>

<b>Vănbản chương trình </b>
Program Hanh_trinh_ki_tu;
Uses Crt;



Const D : Array[1..2] of shortint= (0,1);
C : Array[1..2] of shortint= (1,0);
Fi = ’HT_KITU.INP’;


Var Kt,F : Array[1..32,1..32] of Char;
S : string;


t : word;
dem : longint;
Procedure Init;
Var k,i,j : byte;
G : Text;
Begin


Assign(G,Fi); Reset(G);
Read(G,S); t:= length(S);
Fillchar(F,sizeof(F),’ ’);
F[1,1]:=’*’; k:= 0;
For i:= 1 to t do
begin


For j:=1 to t do
begin


Kt[i,j]:= S[j+k];


If Kt[i,j] = #0 then Kt[i,j]:= ’ ’;
end;


inc(k);


end;
Close(G);
End;


Procedure Write_Out;
Var i,j : Byte;


Begin
Inc(dem);


TextColor(Red); Writeln(’Hanh trinh thu:’,dem);
For i:=1 to t do


begin


For j:=1 to t do
If F[i,j]=’*’ then
begin


TextColor(White); Write(’* ’)
end


</div>
<span class='text_page_counter'>(4)</span><div class='page_container' data-page=4>

TextColor(Green);Write(Kt[i,j],’ ’);
end;


Writeln;
end;
Readln;
End;



Procedure Try(i,j,h: byte);
Var k,x,y: byte;


Begin


If h = t then Write_Out else
begin


For k:=1 to 2 do
begin


x:= i + D[k]; y:= j + C[k];
F[x,y]:=’*’;


Try(x,y,h+1);
F[x,y]:=’ ’;
end;
end;
End;
BEGIN
Clrscr;
Init;
Try(1,1,1);
END.


<b>Bài 2: Biểu thức zero </b>


Cho một số tự nhiên N ≤ 9. Giữa các số từ 1 đến N hãy thêm vào cácdấu + và - sao cho
kết quả thu được bằng 0. Hãy viết chương trình tìmtất cả các khả năng có thể.



<i>Dữ liệu vào: Lấy từ file văn bản ZERO.INP với một dòng ghi số N. </i>
<i>Dữ liệu ra: Ghi vào file văn bản có tên ZERO.OUT có cấu trúc nhưsau: </i>
- Dịng đầu ghi sốlượng kết quả tìm được.


- Các dịng sau mỗidịng ghi một kết quả tìm được.
<b>Ví dụ </b>


</div>
<span class='text_page_counter'>(5)</span><div class='page_container' data-page=5>

áp dụng thuật toán đệ quy quay lui để giải quyết bài toánnay, ta sẽ dùng thủ tục đệ quy
Try(i). Giả sử ta đã điền các dấu’+’ và ’-’ vào các số từ 1 đến i, bây giờ cần điền các
dấugiữa i và i + 1. Ta có thể chọn một trong ba khả năng: hoặc là điềndấu ’+’, hoặc là
điền dấu ’-’, hoặc là không điền dấu nào cả.Khi đã chọn một trong ba khả năng trên, ta
tiếp tục lựa chọn dấuđể điền vào giữa i + 1 và i + 2 bằng cách gọi đệ quy Try(i+1). Ta
sẽlần lượt duyệt tất cả các khả năng đó để tìm tất cả các nghiệmcủa bài tốn, như vậy bài
tốn sẽ khơng bị thiếu nghiệm.


Nếu i = N ta sẽ kiểm tra xem cách điền đó có thoả mãn kết quảbằng 0 hay không. Để
kiểm tra ta dùng thủ tục Test trong chương trình. Nếutổng đúng bằng 0 thì cách điền đó là
một nghiệm của bài tốn, taghi nhận nó. Nếu i < N thì tiếp tục gọi Try(i+1). Trong
chương trìnhta dùng biến dem để đếm các cách điền thoả mãn, còn mảng M kiểu string sẽ
ghi nhận mọi cách điền dấu thoả mãn yêu cầu bài toán.


<b>Văn bản chương trình </b>
Program Zero_sum;


Type MangStr = array[1..15] of string;
Const Fi =’ZERO.INP’;


Fo =’ZERO.OUT’;


Dau : array[1..3] of string[1] = (’-’,’+’,’’);



S : array[1..9] of char =(’1’,’2’,’3’,’4’,’5’,’6’,’7’,’8’,’9’);
ChuSo = [’1’..’9’];


Var N,k,dem: byte;


D : array[2..9] of string[1];
F : Text;


St : String;
M : MangStr;


Procedure Write_out;
Var i : byte;


Begin


Assign(F,Fo); Rewrite(F);
Writeln(F,dem);


For i:= 1 to dem do writeln(F,M[i],’ = 0’);
Close(F); Halt;


End;


Procedure Read_inp;
Begin


Assign(F,Fi); Reset(F);
Read(F,N); Close(F);


If N < 3 then write_out;
End;


Function DocSo(S : String): longint;
Var M : longint;


</div>
<span class='text_page_counter'>(6)</span><div class='page_container' data-page=6>

Begin
M:= 0; t:= 0;


If S[k] in [’+’,’-’] then
begin


t:= k; Inc(k);
end;


While (k<= length(S)) and (s[k] in ChuSo) do
begin


m:= m*10 + ord(s[k]) - ord(’0’);
Inc(k);


end;


If (t <> 0) and (S[t] = ’-’) then DocSo:= -M
else DocSo:= M;


End;


Procedure Test;
Var St : string;


i : byte;


T : longint;
Begin


St:= ’1’; k:= 1; T:= 0;


For i:= 2 to N do St:= St + D[i] + S[i];


While k < length(St) + 1 do T:= T + DocSo(St);
If T = 0 then


begin


Inc(dem); M[dem]:= St;
end;


End;


Procedure Try(i: byte);
Var j : byte;


Begin


For j:= 1 to 3 do
begin


D[i]:= Dau[j];


If i = N then Test else try(i+1);


end;


End;
BEGIN
Read_inp;
Try(2);
Write_out;
END.


<b>Bài 3: Xổ số điện toán</b>


</div>
<span class='text_page_counter'>(7)</span><div class='page_container' data-page=7>

một thẻ gồm M ô (đánh số từ 1 đếnM). Người chơi được chọn K ô trong số các ô đã cho
bằng cách đánhdấu các ơ được chọn. Sau đó các thẻ này được đưa vào máy tínhđể xử lý.
Máy tính chọn ra K ô ngẫu nhiên (gọi là các ô kết quả) và chấmđiểm từng thẻ dựa vào kết
quả đã sinh. Cứ mỗi ơ chọn đúng vớiơ kết quả thì thẻ chơi được tính 1 điểm. Giả thiết
biết các ơchọn cũng như các điểm tươngứng của từng thẻ chơi, hãy xác định tất cả các kết
quả có thể cómà máy sinh ra.


<i>Dữ liệu vào đọc từ file vănbản XOSO.INP gồm: </i>
- Dòng đầu ghi cácsố N, M, K


- Dòng thứ i trongN dòng tiếp ghi thẻ chơi của người i gồm K+1 số: K số đầu là các
sốhiệu


của các ôchọn, cuối cùng là điểm tương ứng.


Ghi kết quả ra file văn bản XOSO.OUT, mỗi dòng là một kết quả gồmK số ghi số hiệu
các ô mà máy đã sinh.


<i><b>Ghi chú:</b></i>



- Các số trên cùng mộtdòng trong các file vào/ ra, được ghi cách nhau ít nhất một dấu
trắng.


- Giới hạn kích thước:N ≤ 100, M ≤50, K ≤10.


- Dữ liệu vào trong cáctest là hợp lệ và đảm bảo có ít nhất một đáp án.
<b>Ví dụ:</b>


<b>Hướng dẫn giải </b>


Ta nhận thấy rằngmỗi nghiệm của bài tốn chính là một cấu hình của tổ hợp chập K
củaM phần tử. Ta áp dụng thuật toán quay lui để duyệt mọi cấu hình tổhợp để tìm ra cấu
hình thoả mãn. Tuy nhiên để giảm bớt số lần duyệtta cần phải loại những thẻ mà chúng
có tổng điểm bằng 0 và cầnđánh dấu những thẻ đã được chọn.


Dùng mảng ok[0..51] of boolean để phân biệt giữa ơ có điểm và những ơ khơng có điểm.
Nếu ok[i]= false thìcho biết thẻ thứ i khơng có điểm. Cịn logic[i,j] = true cho ta biết
người thứ i đánh dấu vàothứ j của thẻ.


<b>Văn bản chương trình </b>
Program Xoso_dien_toan;


Type MangA = array[0..100,0..11] of byte;
MangBool = array[0..51] of boolean;


MangLogic = array[0..101,0..51] of boolean;
Cauhinh = array[0..11] of byte;


</div>
<span class='text_page_counter'>(8)</span><div class='page_container' data-page=8>

B : Cauhinh;


Ok : MangBool;
Diem : integer;
Logic : MangLogic;
F : Text;


Procedure Init;
Begin


Fillchar(A,sizeof(A),0);
Fillchar(B,sizeof(B),0);
Fillchar(ok,sizeof(ok),1);
Fillchar(logic,sizeof(logic),0);
End;


Procedure Read_inp;
Var i,j : byte;


Begin


Assign(F,Fi); Reset(F);
Readln(F,N,M,K);
For i:= 1 to N do
begin


For j:= 1 to k do
begin


Read(f,A[i,j]); Logic[i,A[i,j]]:= true;
end;



Read(F,A[i,k+1]); Inc(diem,A[i,k+1]);
If A[i,k+1] = 0 then


For j:= 1 to k do ok[A[i,j]]:= false;
end;


Close(F);
End;


Function Chapnhan(j: byte): boolean;
Var v : byte;


Begin


Chapnhan:= false;
For v:= 1 to n do


If (A[v,K+1] = 0) and logic[v,j] then exit;
Chapnhan:=true;


End;


Procedure Rutgon(j: byte);
Var i : byte;


Begin


</div>
<span class='text_page_counter'>(9)</span><div class='page_container' data-page=9>

begin


Dec(A[i,k+1]);Dec(diem);


end;


End;


Procedure Morong(j: byte);
Var i : byte;


Begin


For i:= 1 to N do
If logic[i,j] then
begin


Inc(A[i,k+1]); Inc(diem);
end;


End;


Procedure Write_out;
Var d: byte;


Begin


For d:= 1 to K do write(f,B[d],’ ’); Writeln(F);
End;


Procedure Try(i:byte);
Var j: byte;


Begin



For j:= B[i-1] + 1 to M - K + i do
If ok[j] and chapnhan(j) then
begin


B[i]:= j;
Ok[j]:= false;
Rutgon(j);


If (diem = 0) and (i = k) then write_out
else if i < k then try(i+1);


ok[j]:= true;
Morong(j);
end;
End;


Procedure Run;
Begin


Assign(F,Fo); Rewrite(F);
Try(1);


</div>
<span class='text_page_counter'>(10)</span><div class='page_container' data-page=10>

Read_inp;
Run;
End.


<b>Bài 4: Bộ bài Domino với bản đồ số</b>


Bộ bài domino gồm 28 quân đánh số từ 1 đến 28. Mỗi quân bài là một thanh hình chữ


nhật được chia làm hai hình vng bằng nhau. Trong đó người ta ghi các số từ 0 (để
trống) đến 6 bằng cách trổ các dấu tròn trắng. Dưới đây liệt kê 28 quân bài domino:


Sắp xếp 28 quân bài domino ta có thể tạo ra một hìmh chữ nhật kích thước 7*8 ơ vng.
Mỗi cách sắp xếp như vậy sẽ tạo ra một bản đồ số. Ngược lại, mỗi bản đồ số có thể tương
ứng với một số cách xếp.


Ví dụ bản đồ số:
<b>4 2 5 2 6 3 5 4 </b>
<b>5 0 4 3 1 4 1 1 </b>
<b>1 2 3 0 2 2 2 2 </b>
<b>1 4 0 1 3 5 6 5 </b>
<b>4 0 6 0 3 6 6 5 </b>
<b>4 0 1 6 4 0 3 0 </b>
<b>6 5 3 6 2 1 5 3</b>


tương ứng với hai cách xếp mô tả bởi hai bảng số sau:
<b>16 16 24 18 18 20 12 11 </b>


</div>
<span class='text_page_counter'>(11)</span><div class='page_container' data-page=11>

<b>06 06 24 10 10 20 12 11 </b>
<b>08 15 15 03 03 17 14 14 </b>
<b>08 05 05 02 19 17 28 26 </b>
<b>23 01 13 02 19 07 28 26 </b>
<b>23 01 13 25 25 07 21 04 </b>
<b>27 27 22 22 09 09 21 04</b>


Bài toán đặt ra là cho trước một bảnng số, hãy liệt kê tất cả các cách xếp có thể tạo ra từ
nó.


Dữ liệu vào từ file DOMINO.INP là ma trận 7*8 mô tả bản đồ số ban đầu.



Kết quả ghi ra file DOMINO.OUT dịng đầu là số lượng p cách xếp tìm được. Tiếp theo
là p nhóm dịng, mỗi nhóm gồm 7 dòng ghi các dòng của các bảng tương ứng với một
bảng số tìm được.


<b>Hướng dẫn giải </b>


Vói mỗi qn bài domino ta có thể có hai khả năng xếp vào hình chữ nhật: hoặc là đặt
nằm ngang, hoặc là đặt nằm dọc. Ta sẽ thử tất cả các cách để đặt chúng vào hình chữ nhật
cho đến khi nào đặt được cả 28 quân bài vào hình chữ nhật thì đó là một trong các cách
xếp thoả mãn. Mỗi cách xếp thoả mãn sẽ được lưu vào mảng L[1..10,1..7,1..8].


<b>Văn bản chương trình </b>


Program Bo_bai_domino_voi_cac_ban_do_so;
Type Bandoso = array[1..7,1..8] of byte;
Sothutu = array[0..6,0..6] of byte;
Cauhinh = array[1..10,1..7,1..8] of byte;
Const Fi = ’DOMINO.INP’;


Fo = ’DOMINO.OUT’;
D : array[1..2] of byte = (0,1);
C : array[1..2] of byte = (1,0);
Var A,B : Bandoso;


L : Cauhinh;
Gt : Sothutu;
TS : set of byte;
T,dem: byte;
F : Text;



Procedure Read_inp;
Var i,j,k : byte;
Begin


Assign(F,Fi); Reset(F); dem:= 0;
For i:= 1 to 7 do


begin


For j:= 1 to 8 do read(F,A[i,j]);
Readln(F);


end;


</div>
<span class='text_page_counter'>(12)</span><div class='page_container' data-page=12>

begin


Inc(k); Gt[i,j]:= k; Gt[j,i]:= k;
end;


Close(F);
End;


Function Sott(x: byte) : String;
Var S : String;


Begin
Str(X,S);


If length(S) = 1 then S:= ’0’ + S;


Sott:= S;


End;


Procedure Result;
Var i,j : byte;
Begin


Inc(dem);
For i:= 1 to 7 do


For j:= 1 to 8 do L[dem][i,j]:= B[i,j];
End;


Procedure Try(i,j : byte);
Var k,u,v,x : byte;
Begin


While (j < 8) and (B[i,j] > 0) do inc(j);
If (j = 8) and (B[i,j] > 0) then Try(i+1,1) else
For k:= 1 to 2 do


begin


u:= i + D[k]; v:= j + C[k];


If (u in [1..7]) and (v in [1..8]) and (B[u,v] = 0) then
begin


x:= Gt[A[i,j],A[u,v]];


If not (x in Ts) then
begin


Inc(t); Ts:= Ts + [x];
B[i,j]:= x; B[u,v]:= x;
If t = 28 then Result else


If v = 8 then Try(i+1,1) else Try(i,v+1);
Dec(t); Ts:= Ts - [x];


B[i,j]:= 0; B[u,v]:= 0;
end


</div>
<span class='text_page_counter'>(13)</span><div class='page_container' data-page=13>

Procedure Write_out;
Var k,i,j : byte;
Begin


Assign(F,Fo); Rewrite(F);
Writeln(dem);


For k:= 1 to dem do
begin


For i:= 1 to 7 do
begin


For j:= 1 to 8 do write(F,Sott(L[dem][i,j]),’ ’);
Writeln(F);


end;



Writeln(F); Writeln(F);
end;


Close(F);
End;
BEGIN
Read_inp;
Try(1,1);
Write_out;
END.


<b>Bài 5: Robot qt vơi</b>


Có 9 căn phòng (đánh số từ 1 đến 9) đã được qt 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 qt vơi các phịng. Mỗi rơbơt chỉ qt vơi
một số phịng nhất định. Việc qt 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ì qt mầu xanh,
- Nếu phịng đang có mầu xanh thì qt mầu vàng,
- Nếu phịng đang có mầu vàng thì qt 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ẽ qt 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ìm một phương
án như vậy sao cho lượng vơi phải qt là ít nhất. Giả thiết rằng luợng vôi cho mỗi lượt
quét đối với các phòng là như nhau.


<b>Dữ liệu:</b> đọc từ file văn bản ROBOT.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 qt 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ứ 3 có nội dung: 2356 mô tả rôbôt 3 phụ trách việc quét vôi các phịng 2, 3, 5,
6.


- 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 quy ước: ký tự T chỉ mầu trắng, ký tự X chỉ mầu
xanh, ký tự V chỉ mầu vàng.


</div>
<span class='text_page_counter'>(14)</span><div class='page_container' data-page=14>

- 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).
<b>Ví dụ </b>


<b>Hướngdẫn giải </b>


Ta sẽ giải bài tốn bằng cách duyệt theo cây tìm kếm. Với mỗi con robot ta có thể khơng
gọi hoặc sẽ gọi tối đa là hai lần, do đó là sẽ có ba cách lựa chọn. Ta sẽ lần lượt duyệt các
danh sách để gọi các con robot. Vì có tất cả 9 danh sách nên ta phải duyệt tối đa là 39


cách gọi. Do bài tốn địi hỏi là lượng vơi ít nhất nên ta sẽ tìm cách gọi nào là tối ưu nhất.
Để giảm bớt số lần duyệt ta có thể dùng thêm cận để kiểm tra điều kiện có thực hiện tiếp
hay khơng. Nếu ở bước thứ i ta cần gọi là S robot là số lần gọi tối ưu lúc đó là Min thì
nếu S > min thì ta có thể nhánh này của cây và quay lại bước thứ i − 1, nếu S < min thì ta
có thể tiếp tục đuyệt.


<b>Bài 6: Nhà du hành vũ trụ</b>


Một nhà du hành vũ trụ bị lạc vào một hành tinh được thống trị bởi các con robot. Giả sử
hành tinh được chia thành một mảng hình chữ nhật các ơ vng kích thước M X N ( M,N
≤ 8). Tất cả mọi con robot đều tìm cách tiến lại nhà du hành để tiêu diệt, cịn nhà du hành


thì tìm cách tránh xa các con robot. Cứ sau một dơn vị thời gian nhà du hành có thể đi
theo 4 hướng Đông, Tây, Nam, Bắc hoặc đứng yên. Tất cả các con robot được lập trình đi
theo 1 trong 8 hướng kể cả đường chéo sao cho khoảng cách từ con robot đến nhà du
hành là nhỏ nhất (khoảng cách này không lớn hơn khoảng cách ở thời điểm trước) trong
đó đường chéo được tính theo cơng thức hình học thơng thường. Các con robot ln
chuyển động theo nhịp thời gian.


Nếu hai con robot cùng đến một ơ thì cả hai con robot này bị nổ tung và để lại trên ơ đó
một nhiệt độ huỷ diệt được duy trì mãi và nhiệt độ này đủ để phá huỷ các con robot hoặc
nhà du hành chẳng may đặt chân lên ơ đó. Ơ này trở thành nguy hiểm.


Tất cả các con robot không được lập trình để tránh các ơ nguy hiểm hoặc tránh đụng độ
nhau mà chỉ được lập trình để gần nhà du hành một cách máy móc.


Khi một hoặc nhiều robot cùng du hành ở cùng một ơ vng thì nhà du hành bị tiêu diệt.
Nhà du hành không thể đi tới một ơ đang có robot.


</div>
<span class='text_page_counter'>(15)</span><div class='page_container' data-page=15>

- Dòng đầu tiên chứa hai số M và N,


- Trong M dòng tiếp theo chứa bản đồ của hành tinh: mỗi dòng chứa một xâu văn bản
(đặt ngay từ đầu dịng) gồm các kí tự ’0’, ’1’, ’2’ với ý nghĩa sau:


’0’: ơ rỗng ’1’: ơ có một robot ’2’: ơ có nhà du hành.


Kết quả được in ra màn hình và ghi vào văn bản DUHANH.OUT có nội dung như sau:
- Dòng đầu ghi số đơn vị thời gian nhà du hành tồn tại trên hành tinh (quy ước ghi −1 nếu
anh ta tồn tại mãi mãi).


- ứng với mỗi thời điểm có M dịng trên file output bản đồ hành tinh trong lịch trình, mỗi
thời điểm cách nhau một dịng trống.



Ví dụ: Phần đầu của một lịch trình được thể hiên như sau:


</div>
<span class='text_page_counter'>(16)</span><div class='page_container' data-page=16>

<b>Hướng dẫn giải </b>


Sau mỗi bước hoặc robot gần người thêm một dơn vị khoảng cách hoặc không gian bị
hạn chế thêm một đơn vị độ dài cả về chiều rộng lẫn chiều dài, do đó ta đi đến khẳng
định: nếu người tồn tại sau K = Min{M,N} bước thì người tồn tại mãi mãi hay nếu người
<i>bị robot ăn thịt thì khơng thể tồn tại sau K bước di chuyển.</i>


Với khẳng định trên đây lặp không quá K bước trong đó mỗi bước lặp liên quan đến việc
thực hiện 5 cách đi trong bước. Như vậy tổng số bước không vượt quá 5 K<sub> thuật toán.</sub>


</div>

<!--links-->

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×