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à [r]
(1)Lê Sỹ Hùng(Sưu Tầm) Hương Sơn Hà Tĩnh
Một tốn liệt kê tổ hợp ln cần phải đảm bảo hai nguntắc, là: khơng bỏ sót cấu hình khơng trùnglặp cấu hình Có thể nói phương pháp liệt kê cách cuốicùng để giải số toán tổ hợp Mộttrong những phương pháp liệt kê có tính phổ dụng cao phươngpháp quay lui
Nội dung phương pháp việc xây dựng dần cácthành phần cấu hình cách thử tất khả Giả thiếtcấu hình cần tìm mơ tả giá trị (x ,x , ,x N ).Giả sử xác định i - thành phần (x ,x , ,x i-1 ),bây
ta xác định thành phần x i cách duyệt tất cảcác khả đề cử cho (đánh
số từ đến n i ).Với khả j, kiểm tra xem j có chấp nhận hay khơng Cóthể
có hai trường hợp xảy ra:
- Nếu j chấp nhận xác định x i theo j, sau j = N ta 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ả mà mà khơng có khả chấp nhận 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 tìm kiếm.Khơng gian tìm kiếm lớn hay nhiều khả tìm kiếm câytìm kiếm lớn, nhiều nhánh Vì hạn chế bỏ bớt cácnhánh vơ nghiệm tìm kiếm tiết kiệm thời gianvà nhớ, tránh bị tràn liệu Quá trình tìm kiếm lời giải theothuật tốn quay lui mơ tả mơ hình tìm dướiđây:
Cần phải lưu ý ta phải ghi nhớ bước qua,những khả thử để tránh trùng lặp Những thông tin nàyđược lưu trữ theo kiểu liệu ngăn xếp - Stack ( vào sau trước) - nên thuật tốn phù hợp thểhiện thủ tục đệ quy Ta mơ tả bước xác định x i thủ tục đệ quy sau:
Procedure Try (i: integer); Var j : integer;
Begin
For j:= 1to ni
(2)(xác định xi theo j )
if i = N then (ghi nhận cấu hình) else try(i+1);
End; End;
Trong thủ tục mô tả trên, điều quan trọng đưa rađược danh sách khả năngđề cử xác định giá trịcủa biểu thức logic [ chấp nhận j ] Ngoài việc phụ thuộc j, giá trị phụ thuộc vào việc chọn khả i - 1bước trước Trong trường hợp vậy, cần ghi nhớ trạng thái trìnhsau [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 ghi
nhận nhờ số biến tổng thể(global), gọi biến trạng thái
Dễ thấy tốn vơ nghiệm ta duyệt hết khảnăng mà khơng có khả thoả mãn yêu cầu Ta nói vét cạn trường hợp.Chú ý đến lúc ta phải lùi liên tiếp nhiều lần.Từ suy rằng, thơng thường tốn vơ nghiệm khơng thể lùiđược Thuật tốn khơng có tính khả thi cao dùng thủtục đệ quy dễ bị lỗi tràn Stack
Bài 1: Hành trình ký tự Cho tệp văn HT_KITU.INP chứa dịng ký tự chiều dài khơngq 32 Hãy lập trình thực cơng việc sau: Lần lượt đọc cácdịng vào 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 hình Xuấtphát từ góc trái (chữ V), theo hướng để xâydựng lại xâu cho Với hành trình thành cơng in số thứtự hành trình hành trình lưới, ký tự hànhtrình thay dấu ’*’ Ví dụ:
Sau lời giải phải ấn ENTER để in lời giải tiếp Hướngdẫn giải
Tổ chức hai mảng hai chiều F, Kt[1 32,1 32] of Char.Mảng Kt dùngđể tạo ma trận kí tự dạng tam giác gồm kí tự từ xâuS đọc từ file liệu Mảng F dùng để ghi nhận hành trình thànhcơng, (i,j) thuộc hành trình F[i,j] = ’*’
Sau 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 hành trình Giả sử ta đangở (i,j) hành trình xâu kí tự độ dài h ≤ length(S ) Nếu h = length(S )thì ta hành trình ta ghi nhận nó, in hìnhhành trình Cịn h < length(S )thì từ (i,j) tasẽ theo hai hướng đến (i,j+1) hoặclà ô (i+1,j) Từmỗi ô ta lại tiếp tục đến khác để tìm hành trình Qtrình tiếp tục thựchiện duyệt hết nghiệm toán
(3)Vănbản chương trình 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:= to t begin
For j:=1 to t 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
begin
For j:=1 to t If F[i,j]=’*’ then begin
TextColor(White); Write(’* ’) end
(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 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ài 2: Biểu thức zero
Cho số tự nhiên N ≤ Giữa số từ đến N thêm vào cácdấu + - cho kết thu Hãy viết chương trình tìmtất khả
Dữ liệu vào: Lấy từ file văn ZERO.INP với dòng ghi số N Dữ liệu ra: Ghi vào file văn có tên ZERO.OUT có cấu trúc nhưsau: - Dịng đầu ghi sốlượng kết tìm
- Các dịng sau mỗidịng ghi kết tìm Ví dụ
(5)áp dụng thuật toán đệ quy quay lui để giải toánnay, ta dùng thủ tục đệ quy Try(i) Giả sử ta điền dấu’+’ ’-’ vào số từ đến i, cần điền dấugiữa i i + Ta chọn ba khả năng: điềndấu ’+’, điền dấu ’-’, không điền dấu cả.Khi chọn ba khả trên, ta tiếp tục lựa chọn dấuđể điền vào i + i + cách gọi đệ quy Try(i+1) Ta sẽlần lượt duyệt tất khả để tìm tất nghiệmcủa toán, toán không bị thiếu nghiệm
Nếu i = N ta kiểm tra xem cách điền có thoả mãn kết quảbằng hay không Để kiểm tra ta dùng thủ tục Test chương trình Nếutổng cách điền nghiệm tốn, taghi nhận Nếu i < N tiếp tục gọi Try(i+1) Trong chương trìnhta dùng biến dem để đếm cách điền thoả mãn, mảng M kiểu string ghi nhận cách điền dấu thoả mãn u cầu tốn
Văn chương trình 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:= to dem 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 < then write_out; End;
Function DocSo(S : String): longint; Var M : longint;
(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) 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:= to N St:= St + D[i] + S[i];
While k < length(St) + T:= T + DocSo(St); If T = then
begin
Inc(dem); M[dem]:= St; end;
End;
Procedure Try(i: byte); Var j : byte;
Begin
For j:= to 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ài 3: Xổ số điện toán
(7)một thẻ gồm M ô (đánh số từ đếnM) Người chơi chọn K ô số ô cho cách đánhdấu chọn Sau thẻ đưa vào máy tínhđể xử lý Máy tính chọn K ngẫu nhiên (gọi ô kết quả) chấmđiểm thẻ dựa vào kết sinh Cứ ô chọn vớiô kết thẻ chơi tính điểm Giả thiết biết ôchọn điểm tươngứng thẻ chơi, xác định tất kết cómà máy sinh
Dữ liệu vào đọc từ file vănbản XOSO.INP gồm: - Dòng đầu ghi cácsố N, M, K
- Dòng thứ i trongN dòng tiếp ghi thẻ chơi người i gồm K+1 số: K số đầu sốhiệu
của ôchọn, cuối điểm tương ứng
Ghi kết file văn XOSO.OUT, dòng kết gồmK số ghi số hiệu ô mà máy sinh
Ghi chú:
- Các số mộtdòng file vào/ ra, ghi cách dấu trắng
- Giới hạn kích thước:N ≤ 100, M ≤50, K ≤10
- Dữ liệu vào cáctest hợp lệ đảm bảo có đáp án Ví dụ:
Hướng dẫn giải
Ta nhận thấy rằngmỗi nghiệm tốn cấu hình tổ hợp chập K củaM phần tử Ta áp dụng thuật toán quay lui để duyệt cấu hình tổhợp để tìm 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 thẻ mà chúng có tổng điểm cầnđánh dấu thẻ chọn
Dùng mảng ok[0 51] of boolean để phân biệt có điểm 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 thẻ
Văn chương trình 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;
(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:= to N begin
For j:= to k 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] = then
For j:= to k ok[A[i,j]]:= false; end;
Close(F); End;
Function Chapnhan(j: byte): boolean; Var v : byte;
Begin
Chapnhan:= false; For v:= to n
If (A[v,K+1] = 0) and logic[v,j] then exit; Chapnhan:=true;
End;
Procedure Rutgon(j: byte); Var i : byte;
Begin
(9)begin
Dec(A[i,k+1]);Dec(diem); end;
End;
Procedure Morong(j: byte); Var i : byte;
Begin
For i:= to N If logic[i,j] then begin
Inc(A[i,k+1]); Inc(diem); end;
End;
Procedure Write_out; Var d: byte;
Begin
For d:= to K write(f,B[d],’ ’); Writeln(F); End;
Procedure Try(i:byte); Var j: byte;
Begin
For j:= B[i-1] + to M - K + i 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);
(10)Read_inp; Run; End
Bài 4: Bộ Domino với đồ số
Bộ domino gồm 28 quân đánh số từ đến 28 Mỗi quân hình chữ nhật chia làm hai hình vng Trong người ta ghi số từ (để trống) đến cách trổ dấu tròn trắng Dưới liệt kê 28 quân domino:
Sắp xếp 28 quân domino ta tạo hìmh chữ nhật kích thước 7*8 ô vuông Mỗi cách xếp tạo đồ số Ngược lại, đồ số tương ứng với số cách xếp
Ví dụ đồ số: 4 5 4 1 1 2 2 1 4 6 4 6 3
tương ứng với hai cách xếp mô tả hai bảng số sau: 16 16 24 18 18 20 12 11
(11)06 06 24 10 10 20 12 11 08 15 15 03 03 17 14 14 08 05 05 02 19 17 28 26 23 01 13 02 19 07 28 26 23 01 13 25 25 07 21 04 27 27 22 22 09 09 21 04
Bài toán đặt cho trước bảnng số, liệt kê tất cách xếp tạo từ
Dữ liệu vào từ file DOMINO.INP ma trận 7*8 mô tả đồ số ban đầu
Kết ghi file DOMINO.OUT dòng đầu số lượng p cách xếp tìm Tiếp theo p nhóm dịng, nhóm gồm dịng ghi dòng bảng tương ứng với bảng số tìm
Hướng dẫn giải
Vói quân domino ta có hai khả xếp vào hình chữ nhật: đặt nằm ngang, đặt nằm dọc Ta thử tất cách để đặt chúng vào hình chữ nhật đặt 28 quân vào hình chữ nhật cách xếp thoả mãn Mỗi cách xếp thoả mãn lưu vào mảng L[1 10,1 7,1 8]
Văn chương trình
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:= to
begin
For j:= to read(F,A[i,j]); Readln(F);
end;
(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) = then S:= ’0’ + S; Sott:= S;
End;
Procedure Result; Var i,j : byte; Begin
Inc(dem); For i:= to
For j:= to 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) inc(j); If (j = 8) and (B[i,j] > 0) then Try(i+1,1) else For k:= to
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 = then Try(i+1,1) else Try(i,v+1); Dec(t); Ts:= Ts - [x];
B[i,j]:= 0; B[u,v]:= 0; end
(13)Procedure Write_out; Var k,i,j : byte; Begin
Assign(F,Fo); Rewrite(F); Writeln(dem);
For k:= to dem begin
For i:= to begin
For j:= to 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ài 5: Robot quét vôi
Có phịng (đánh số từ đến 9) quét vôi với mầu trắng, xanh vàng Có rơbơt (đánh số từ đến 9) phụ trách việc qt vơi phịng Mỗi rơbơt qt vơi số phịng định Việc qt vơi thực nhờ chương trình cài sẵn theo qui tắc:
- Nếu phịng có mầu trắng qt mầu xanh, - Nếu phịng có mầu xanh qt mầu vàng, - Nếu phịng có mầu vàng quét mầu trắng
Cần phải gọi số rôbôt quét vôi (mỗi lần rơbơt, rơbơt gọi nhiều lần có rơbơt khơng gọi Rơbơt gọi qt vơi tất phịng mà phụ trách) để cuối phịng có mầu trắng Hãy tìm phương án cho lượng vơi phải qt Giả thiết luợng vơi cho lượt qt phịng
Dữ liệu: đọc từ file văn ROBOT.INP gồm dòng:
- dòng đầu, dịng mơ tả danh sách phịng qt vôi rôbôt theo thứ tự từ rôbôt đến rơbơt Mỗi dịng gồm số hiệu phòng viết sát Chẳng hạn dòng thứ có nội dung: 2356 mơ tả rơbơt phụ trách việc qt vơi phịng 2, 3, 5,
- Dịng cuối mơ tả mầu vơi ban đầu phòng Dòng gồm ký tự viết sát nhau, ký tự thứ i biểu diễn mầu vơi phịng i với quy ước: ký tự T mầu trắng, ký tự X mầu xanh, ký tự V mầu vàng
(14)- Trái lại ghi dãy thứ tự rôbôt gọi (các số hiệu rơbơt viết sát nhau) Ví dụ
Hướngdẫn giải
Ta giải toán cách duyệt theo tìm kếm Với robot ta không gọi gọi tối đa hai lần, có ba cách lựa chọn Ta duyệt danh sách để gọi robot Vì có tất danh sách nên ta phải duyệt tối đa 39
cách gọi Do tốn địi hỏi lượng vơi nên ta tìm cách gọi tối ưu Để giảm bớt số lần duyệt ta dùng thêm cận để kiểm tra điều kiện có thực tiếp hay không Nếu bước thứ i ta cần gọi S robot số lần gọi tối ưu lúc Min S > ta nhánh quay lại bước thứ i − 1, S < ta tiếp tục đuyệt
Bài 6: Nhà du hành vũ trụ
Một nhà du hành vũ trụ bị lạc vào hành tinh thống trị robot Giả sử hành tinh chia thành mảng hình chữ nhật vng kích thước M X N ( M,N ≤ 8) Tất robot tìm cách tiến lại nhà du hành để tiêu diệt, nhà du hành tìm cách tránh xa robot Cứ sau dơn vị thời gian nhà du hành theo hướng Đông, Tây, Nam, Bắc đứng yên Tất robot lập trình theo hướng kể đường chéo cho khoảng cách từ robot đến nhà du hành nhỏ (khoảng cách không lớn khoảng cách thời điểm trước) đường chéo tính theo cơng thức hình học thơng thường Các robot chuyển động theo nhịp thời gian
Nếu hai robot đến hai robot bị nổ tung để lại nhiệt độ huỷ diệt trì nhiệt độ đủ để phá huỷ robot nhà du hành chẳng may đặt chân lên Ơ trở thành nguy hiểm
Tất robot khơng lập trình để tránh ô nguy hiểm tránh đụng độ mà lập trình để gần nhà du hành cách máy móc
Khi nhiều robot du hành vng nhà du hành bị tiêu diệt Nhà du hành tới có robot
(15)- Dòng chứa hai số M N,
- Trong M dòng chứa đồ hành tinh: dòng chứa xâu văn (đặt từ đầu dịng) gồm kí tự ’0’, ’1’, ’2’ với ý nghĩa sau:
’0’: ô rỗng ’1’: có robot ’2’: có nhà du hành
Kết in hình ghi vào văn DUHANH.OUT có nội dung sau: - Dòng đầu ghi số đơn vị thời gian nhà du hành tồn hành tinh (quy ước ghi −1 tồn mãi)
- ứng với thời điểm có M dịng file output đồ hành tinh lịch trình, thời điểm cách dịng trống
Ví dụ: Phần đầu lịch trình thể hiên sau:
(16)Hướng dẫn giải
Sau bước robot gần người thêm dơn vị khoảng cách không gian bị hạn chế thêm đơn vị độ dài chiều rộng lẫn chiều dài, ta đến khẳng định: người tồn sau K = Min{M,N} bước người tồn mãi hay người bị robot ăn thịt khơng thể tồn sau K bước di chuyển.
Với khẳng định lặp không K bước bước lặp liên quan đến việc thực cách bước Như tổng số bước khơng vượt q K thuật tốn.