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

Phương pháp Quay 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 (129.89 KB, 20 trang )

PHƯƠNG PHÁP QUAY LUI
A. LÝ THUYẾT
Phương pháp tốt nhất để giải bài toán trong tin học là biết sử dụng và phối hợp uyển
chuyển nhiều thuật toán, không được lạm dụng, coi thường bất kỳ một phương pháp nào.
- Phương pháp quay lui được dùng để liệt kê cấu hình tổ hợp hoặc đếm cấu hình tổ hợp.
- Phương pháp quay lui có thể được sử dụng nếu ta xác định được tập các giá trị mà
phần tử x[i] của cấu hình (x[1], x[2], ..., x[n]) có thể nhận.
Tập các giá trị mà phần tử x[1] nhận có thể trùng hoặc không trùng với tập các giá trị
mà phần tử x[2], ..., x[n] nhận (phụ thuộc vào từng bài toán cụ thể).
Thủ tục quay lui có thể mô tả như sau:
Procedure Try(i);
Var ...
Begin
For <mọi giá trị V có thể gán cho xi> do
If <chấp nhận V> then
Begin
x[i]:=V;
If i=n then
<Xử lí cấu hình tìm được>
Else
Begin
<Đánh dấu một số giá trị, nếu cần>
Try(i+1)
<Hủy bỏ việc đánh dấu các giá trị, nếu cần>
End;
End;
End;
Những khó khăn khi sử dụng PP quay lui:
- Việc xác định tập các giá trị mà phần tử x[i] của cấu hình có thể nhận.
- Khi gán x[i]=V rất có thể người dùng phải đánh dấu một số giá trị để phần tử x[i+1]
và các phần tử đứng sau không được phép nhận giá trị đó nữa.


- Phương pháp quay lui sẽ khó thực hiện khi dữ liệu bài toán lớn.
Các bước tiến hành khi dùng PP quay lui:
- Xác định cấu hình tổng quát: Cấu hình có bao nhiêu phần tử, thuộc kiểu dữ liệu nào?
- Xác định tập giá trị cho các phần tử của cấu hình
- Xác định bảng lưu kết quả.
- Bảng dùng để đánh dấu các giá trị (nếu có).

1


B. MỘT SỐ BÀI TOÁN
Bài số 1: Liệt kê các dãy bit độ dài bằng N.
Ví dụ:
binary.inp
binary.out
3
000
001
010
011
100
101
110
111
Hướng dẫn:
- Cấu hình (x1, x2, x3, …, xn)
- x[i] có thể nhận {0; 1}
const fi='binary.inp';
fo='binary.out';
var f:text;

n:byte;
x:array[1..100] of byte;
{===============================}
procedure docdl;
begin
assign(f,fi);
reset(f);
readln(f,n);
close(f);
end;
{===============================}
procedure Bina(i:byte);
var j,k:byte;
begin
for j:=0 to 1 do
begin
x[i]:=j;
if i=n then
begin
for k:=1 to n do
write(f,x[k]:2);
writeln(f);
end
else
Bina(i+1);
end;
end;
{===============================}
BEGIN
docdl;

fillchar(x,sizeof(x),0);
assign(f,fo);
rewrite(f);
Bina(1);
close(f);
END.
2


Bài số 2: Liệt kê tất cả các tập con gồm k phần tử của tập {1; 2; 3; …; n}
Hướng dẫn:
- Cấu hình (x1, x2, x3, …, xk)
- Để tránh việc lặp đi lặp lại các tập con thì x[i] có thể nhận các giá trị từ
x[i-1]+1 đến n-k+i
- Chú ý đánh chặn x[0]=0;
Ví dụ:
Tapcon.inp
Tapcon.out
3 5
123
124
125
134
135
145
234
235
245
345
const fi='Tapcon.inp';

fo='Tapcon.out';
var f:text;
n,k:longint;
x:array[0..1000] of longint;
{===============================}
procedure Tapcon(i:longint);
var j,m:longint;
begin
for j:=x[i-1]+1 to n-k+i do
begin
x[i]:=j;
if i=k then
begin
for m:=1 to k do
write(f,x[m]);
writeln(f);
end
else
Tapcon(i+1);
end;
end;
{=================================}
BEGIN
assign(f,fi);
reset(f);
readln(f,n,k);
close(f);
x[0]:=0;
assign(f,fo);
rewrite(f);

Tapcon(1);
close(f);
END.
3


Bài số 3: Liệt kê hoán vị
Liệt kê các hoán vị của tập {1; 2; …; n}
Ví dụ:
Hoanvi.inp
Hoanvi.out
3
123
132
213
231
312
321
Hướng dẫn:
- Cấu hình (x1, x2, ..., xn)
- X[i] nhận các giá trị từ 0 đến n-1 trừ các giá trị mà các phần tử trước đã nhận
- Dùng mảng cd để đánh dấu các giá trị đã dùng trong cấu hình.
const fi='Hoanvi.inp';
fo='Hoanvi.out';
var n,i:byte;
f:text;
x:array[1..100] of byte;
cd:array[1..100] of boolean;
{---------------------------}
Procedure Hoanvi(i:byte);

var j,k:byte;
begin
for j:=1 to n do
if cd[j] then
begin
x[i]:=j;
if i=n then
begin
for k:=1 to n do
write(f,x[k]);
writeln(f);
end
else
begin
cd[j]:=false;
Hoanvi(i+1);
cd[j]:=true;
end;
end;
end;
{--------------------------}
BEGIN
assign(f,fi);
reset(f);
readln(f,n);
close(f);
for i:=1 to n do
cd[i]:=true;
assign(f,fo);
rewrite(f);

Hoanvi(1);
close(f);
END.
4


Bài số 4: Mua hàng
Một cửa hàng bán N loại bánh khác nhau, mỗi loại bánh có số lượng rất nhiều đủ để đáp
ứng yêu cầu của khách hàng. Có một người đi mua hàng cần mua K cái bánh. Giả sử người đó
chỉ quan tâm đến loại bánh mà không quan tâm đến cái bánh cụ thể và thứ tự chọn chúng.
Yêu cầu: Hãy cho biết khách hàng đó có bao nhiêu cách khác nhau để chọn mua hàng?
Dữ liệu vào: Cho trong tập tin văn bản MHANG.INP gồm một dãy ghi hai số nguyên
dương N và K (1Dữ liệu ra: Ghi ra file MHANG.OUT một số nguyên là số cách chọn mua hàng
Ví dụ:
MHANG.INP
3 4

MHANG.OUT
15

Hướng dẫn:
- Cấu hình (x1, x2, x3, …, xk), trong đó x[i] là loại loại bánh của cái bánh thứ i mà khác
hàng chọn mua
- Để tránh việc lặp lại thì x[i] có thể nhận giá trị từ x[i-1] đến n
- Chú ý đánh chặn x[0]=1
const fi='Muahang.inp';
fo='Muahang.out';
var x:array[0..50] of longint;
dem,n,k:longint;

f:text;
{-----------------------------------------}
procedure Muahang(i:longint);
var j:longint;
begin
for j:=x[i-1] to n do
begin
x[i]:=j;
if i=k then
dem:=dem+1
else
Muahang(i+1);
end;
end;
{----------------------------------------}
BEGIN
assign(f,fi);
reset(f);
readln(f,n,k);
close(f);
x[0]:=1;
Muahang(1);
assign(f,fo);
rewrite(f);
write(f,dem);
close(f);
END.

5



Bài số 5: Cho dãy số a1; a2; ...; an. Hỏi có bao nhiêu cách chèn các dấu + hoặc – vào trước
các phần tử a[i] để nhận được kết quả bằng M cho trước.
Ví dụ:
DIENDAU.INP
3 0
1 2 3

DIENDAU.OUT
2

(Có 2 cách đó là -1-2+3=0 và +1+2-3=0)
Hướng dẫn:
- Cấu hình (x1, x2, x3, …, xn)
- x[i] có thể nhận {0; 1} với qui ước:
x[i]=0 nếu trước phần tử a[i] là dấu –
x[i]=1 nếu trước phần tử a[i] là dấu +
- Dùng mảng T[1..n] . Trong đó T[i] = tổng giá trị nhận được khi ta điền dấu cho các
phần tử từ phần tử thứ 1 đến phần tử thứ i
const fi='Diendau.inp';
fo='Diendau.out';
var f:text;
t,d,a:array[0..100] of longint;
dem,n,m,i:longint;
{-----------------------------------}
procedure Diendau(i:longint);
var j:longint;
begin
for j:=0 to 1 do
begin

d[i]:=j;
if d[i]=0 then
t[i]:=t[i-1]-a[i]
else
t[i]:=t[i-1]+a[i];
if i=n then
begin
if t[i]=m then
inc(dem);
end
else
Diendau(i+1);
end;
end;
BEGIN
assign(f,fi);
reset(f);
readln(f,n,m);
for i:=1 to n do
read(f,a[i]);
close(f);
t[0]:=0;
Diendau(1);
assign(f,fo);
rewrite(f);
write(f,dem);
close(f);
6



END.

Bài số 6: Biểu thức Zero
Cuội viết liên tiếp các số tự nhiên từ 1 đến N thành dãy: 1 2 3 ... N. Cuội đố Bờm điền
các dấu phép toán + hoặc - vào giữa 2 số tự nhiên liên tiếp sao cho biểu thức thu được có kết
quả bằng 0.
Yêu cầu: Bạn hãy giúp Bờm viết chương trình liệt kê tất cả các cách điền dấu phép
toán thích hợp.
Dữ liệu: Vào từ file văn bản ZERO.INP gồm 1 dòng duy nhất ghi số N (N<10).
Kết quả: Ghi ra file văn bản có tên ZERO.OUT:
• Dòng đầu tiên ghi số M là số cách điền dấu vào biểu thức.


M dòng tiếp theo, mỗi dòng ghi một kết quả tìm được.

Ví dụ:
ZERO.INP
2

ZERO.OUT
0

ZERO.INP
3

ZERO.OUT
1
1+2-3=0

Hướng dẫn:

Dựa vào bài 5 để làm, chú ý là không điền dấu vào trước số 1 (số đầu tiên)
const fi='Zero.inp';
fo='Zero.out';
ft='Zero.txt';
var f,tep:text;
s:string;
m,n,dem:longint;
x,t:array[0..200] of longint;
{========================}
procedure Zero(i:byte);
var j,k:byte;
begin
for j:=0 to 1 do
begin
x[i]:=j;
if x[i]=0 then
t[i]:=t[i-1]+i
else
t[i]:=t[i-1]-i;
if i=n then
begin
if t[n]=0 then
begin
write(f,1);
for k:=2 to n do
if x[k]<>0 then
write(f,'-',k)
else
write(f,'+',k);
writeln(f,'=0');

dem:=dem+1;
end;
end
else
Zero(i+1);
end;
end;
{=====================}
7


BEGIN
assign(f,fi);
reset(f);
readln(f,n);
close(f);
assign(f,ft);
rewrite(f);
x[1]:=1;
t[1]:=1;
Zero(2);
close(f);
assign(tep,fo);
rewrite(tep);
writeln(tep,dem);
reset(f);
while not eof(f) do
begin
readln(f,s);
writeln(tep,s);

end;
close(tep);
close(f);
END.

8


Bài số 7: Liệt kê các cách phân tích số tự nhiên N thành tổng các số tự nhiên ≤N
Hướng dẫn:
- Cấu hình x1, x2, ..., xn
- Dùng mảng T[1..N] để lưu tổng
- x[i] có thể nhận các giá trị từ x[i-1] đến N-T[i-1]
- Đánh chặn T[0]=0 ; x[0]=0 ;
Ví dụ:
PTS.INP
3

PTS.OUT
3=0+0+3
3=0+1+2
3=1+1+1

const fi='PTS.INP';
fo='PTS.OUT';
var t,x:array[0..100] of integer;
n:integer;
f:text;
{-----------------------------------------}
procedure PTS(i:integer);

var j,k:integer;
begin
for j:=x[i-1] to N-t[i-1] do
begin
x[i]:=j;
t[i]:=t[i-1]+j;
if i=n then
begin
if t[i]=N then
begin
write(f,n,' = ');
for k:=1 to n-1 do
write(f,x[k],' + ');
writeln(f,x[n]);
end;
end
else
PTS(i+1);
end;
end;
{----------------------------------------}
BEGIN
assign(f,fi);
reset(f);
readln(f,n);
close(f);
x[0]:=0;
assign(f,fo);
rewrite(f);
PTS(1);

close(f);
END.

9


Bài số 8: Tìm nghiệm
Liệt kê các tập nghiệm nguyên không âm của phương trình: x1+x2+...+xn=S khi biết S và n.
Ví dụ:
TIMN.INP
TIMN.OUT
5 3
5=0+0+5
5=0+1+4
5=0+2+3
5=1+1+3
5=1+2+2
Hướng dẫn:
- Cấu hình x1, x2, ..., xn
- Dùng mảng T[1..N] để lưu tổng
- x[i] có thể nhận các giá trị từ x[i-1] đến S-T[i-1]
- Đánh chặn T[0]=0 ; x[0]=0 ;
const fi='TIMN.INP';
fo='TIMN.OUT';
var t,x:array[0..100] of longint;
s,dem,n:longint;
f:text;
{-----------------------------------------}
procedure TIMN(i:longint);
var j,k:longint;

begin
for j:=x[i-1] to s-t[i-1] do
begin
x[i]:=j;
t[i]:=t[i-1]+j;
if i=n then
begin
if t[i]=s then
begin
write(f,s,' = ');
for k:=1 to n-1 do
write(f,x[k],' + ');
writeln(f,x[n]);
end;
end
else
TIMN(i+1);
end;
end;
{----------------------------------------}
BEGIN
assign(f,fi);
reset(f);
read(f,s,n);
close(f);
assign(f,fo);
rewrite(f);
TIMN(1);
close(f);
END.


10


Bài số 9: Tính tổng
Cho số nguyên dương S và tập A gồm N số nguyên dương a1, a2, ... aN. Ta biết rằng S
có thể viết thành tổng các phần tử trong tập A.
Hãy cho biết tổng này chứa ít nhất là bao nhiêu số hạng.
Ví dụ: Với S=14 và tập A gồm 6 phần tử là 1, 2, 3, 5, 7 , 10 thì có thể viết S theo
nhiều phương án như sau:
S = 1 + 1 + 2 + 10
( 4 số hạng )
S = 1 + 3 + 10
( 3 số hạng )
S=7+7
( 2 số hạng )
.....
trong đó phương án thứ 3 là tối ưu vì chỉ dùng 2 số hạng.
Dữ liệu vào: tập tin văn bản SUM.INP, gồm:
- Dòng đầu tiên là hai số nguyên dương S và n
- Tiếp đến là giá trị a1, a2, ..., aN có thể viết trên nhiều dòng. Các số được viết cách nhau
ít nhất một dấu cách. 1 ≤ S ≤ 10000, 1 ≤ N ≤ 100.
Kết quả: Ghi vào tập tin văn bản SUM.OUT một số nguyên dương k là số số hạng tối thiểu
trong tổng biểu diễn của S.
SUM.INP
SUM.OUT
14 6
2
1 2 3
5 7 10

Hướng dẫn:
- Cấu hình x1, x2, …, xn
- Trong đó x[i] có thể nhận các giá trị a1, a2, …, an
- Dùng mảng T[1..n] để tính tổng các phần tử tại mỗi bước
- Khởi tạo MIN=N
- Mỗi khi tìm thấy T[i]=S thì ta cập nhật lại MIN, ngược lại nếu T[i]gọi thủ tục quay lui cho phần tử x[i+1].
const fi='SUM.INP';
fo='SUM.OUT';
var f:text;
S:word;
n,min:byte;
x,t,a:array[0..100] of word;
{======================================}
procedure docdl;
var k:byte;
begin
assign(f,fi);
reset(f);
readln(f,s,n);
for k:=1 to n do
read(f,a[k]);
close(f);
t[0]:=0;
min:=n;
end;
{======================================}
procedure sum(i:byte);
11



var j:byte;
begin
for j:=n downto 1 do
begin
x[i]:=a[j];
t[i]:=t[i-1]+x[i];
if t[i]=s then
begin
if min>i then
min:=i;
end
else
if (t[i]sum(i+1);
end;
end;
{======================================}
BEGIN
docdl;
sum(1);
assign(f,fo);
rewrite(f);
write(f,min);
close(f);
END.

Bài số 10: Siêu thị may mắn
An được mời tham gia trò chơi “Siêu thị máy tính” do đài truyền hình ZTV tổ chức.
Siêu thị được đặt trong trường quay truyền hình có n mặt hàng được đánh số từ 1 đến n và

mặt hàng thứ i được niêm yết giá là ci đồng, i = 1, 2, …, n. Theo thể lệ của trò chơi, An được
ban tổ chức tặng một thẻ mua hàng có gía trị là s đồng và phải dùng hết số tiền trong thẻ này
để mua hàng trong siêu thị với điều kiện mặt hàng thứi chỉ được mua với số lượng nhiều nhất
là mi, i = 1, 2, …, n. An sẽ là người thắng cuộc nếu tìm được tổng số cách mua hàng thỏa mãn
yêu cầu đặt ra và chỉ ra một cách mua hàng nếu có.
Yêu cầu: Hãy giúp An trở thành người thắng cuộc khi cho bạn biết trước các giá trị
n, s, ci va mi (1≤n≤500; 1≤s≤105; 1≤ci≤104; 1≤mi≤100) với i = 1, 2, …, n.
Dữ liệu: Vào từ file văn bản SMARKET.INP
- Dòng đầu tiên chứa hai số nguyên dương s và n;
- Dòng thứ i trong n dòng tiếp theo chứa 2 số nguyên dương ci và mi với i = 1, 2, …, n.
Kết quả: Ghi ra file văn bản SMARKET.OUT
- Dòng đầu tiên ghi số nguyên d là tổng số cách mua hàng tìm được;
- Nếu d ≥ 1 thì dòng thứ hai ghi một cách mua hàng tìm được là một dãy n số nguyên,
trong dó số hạng thứ i là số lượng mặt hàng thứ i mua được trong cách mua hàng này,
i = 1, 2, …, n.
Ví dụ:
SMARKET.INP
SMARKET.OUT
12 3
2
4 1
0 2 0
6 2
2 1
12


Hướng dẫn:
- Cấu hình (x1, x2, ..., xn) trong đó: x[i] là số lượng chọn đồ vật thứ i.
- X[i] nhận các giá trị từ 0 đến m[i]

- Dùng mảng T để lưu kết quả mỗi bước.
var

n,d:word;
s:longint;
t,c:array[1..500] of word;
sl,dd,m:array[1..500] of byte;
f:text;
{------------------------------------------------}
procedure Readdata;
var i:word;
begin
assign(f,'smarket.inp');
reset(f);
readln(f, s, n);
for i:=1 to n do
readln(f, c[i], m[i]);
for i:=1 to n do begin sl[i]:=0; t[i]:=0; end;
d:=0;
end;
{------------------------------------------------}
procedure Printdata;
var i:word;
begin
assign(f,'smarket.out');
rewrite(f);
writeln(f,d);
for i:=1 to n do
write(f, dd[i]:5);
close(f);

end;
{----------------------------------------------}
procedure try(i:word);
var
j:word;
begin
for j:=0 to m[i] do
begin
sl[i]:=j;
t[i]:=t[i-1]+c[i]*sl[i];
if itry(i+1)
else
if t[i]=s then
begin
d:=d+1;
if d=1 then
dd:=sl;
end;
end;
end;
{------------------------------------}
BEGIN
readdata;
try(1); close(f);
printdata;
END.

13



Bài số 11: Cân vật
Cho N quả cân với các trọng lượng tương ứng là 1kg, 3kg, ..., 3 N-1kg và một cân bàn. Ta
muốn chỉ dùng cân bàn và n quả cân này để cân một vật có trọng lượng M kg trong một lần cân.
Liệu ta có thể cân được không?
Dữ liệu vào: CAN.INP gồm 2 dòng:
- Dòng đầu ghi N
- Dòng thứ hai ghi M
Kết quả : CAN.OUT
- Nếu không cân được ghi KHONG
- Nếu cân được thì có 2 dòng:
+ Dòng đầu chứa số hiệu các quả cân đặt cùng phía với vật được cân (M)
+ Dòng thứ hai là số hiệu các quả cân đặt tại đĩa cân phía bên kia.
Ví dụ:
CAN.INP
CAN.OUT
7
255
236
Hướng dẫn:
- Tương ứng với N quả cân ta có N phần tử x1, x2, …, xn trong đó
+ x[i]=-1 nếu quả cân đặt cùng phía với M
+ x[i]=0 nếu không dùng quả cân thứ i
+ x[i]=1 nếu quả cân đặt phía bên kia M
- Dùng mảng T[1..N] để cập nhật tổng mỗi bước
const fi='CAN.INP';
fo='CAN.OUT';
var f:text;
t,x,a:array[0..100] of longint;
n:byte;

m:longint;
{==============================================}
procedure docdl;
var k:byte;
begin
assign(f,fi);
reset(f);
readln(f,N);
readln(f,M);
close(f);
a[1]:=1;
for k:=2 to n do
a[k]:=a[k-1]*3;
t[0]:=0;
end;
{==============================================}
procedure outkq;
var k:byte;
begin
assign(f,fo);
rewrite(f);
for k:=1 to n do
if x[k]=-1 then
write(f,k:4);
14


writeln(f);
for k:=1 to n do
if x[k]=1 then

write(f,k:4);
close(f);
halt;
end;
{==============================================}
procedure QCAN(i:byte);
var j:integer;
begin
for j:=-1 to 1 do
begin
x[i]:=j;
if x[i]=-1 then
t[i]:=t[i-1]-a[i]
else
if x[i]=0 then
t[i]:=t[i-1]
else
t[i]:=t[i-1]+a[i];
if iQCAN(i+1)
else
if t[i]=M then
outkq;
end;
end;
{==============================================}
BEGIN
docdl;
QCAN(1);
assign(f,fo);

rewrite(f);
write(f,'KHONG');
close(f);
END.

Bài số 12: Xếp hàng mua vé
Có N người sắp hàng mua vé dự buổi hoà nhạc. Ta đánh số họ từ 1 đến n theo thứ tự
đứng trong hàng. Mỗi người cần mua một vé, song người bán vé được phép bán cho mỗi
người tối đa 2 vé. Vì thế một số người có thể rời hàng và nhờ người đứng trước mình mua hộ
vé. Biết ti là thời gian cần thiết để người i mua xong vé cho mình. Nếu người i+1 rời khỏi
hàng và nhờ người i mua hộ vé thì thời gian để người thứ i mua được vé cho cả hai người là ri.
Yêu cầu: Xác định xem những người nào cần rời khỏi hàng và nhờ người đứng trước mua vé
để tổng thời gian phục vụ bán vé là nhỏ nhất.
Dữ liệu: Vào từ file TICK.INP.
- Dòng đầu tiên chứa số n (1- Dòng thứ 2 ghi N số nguyên dương t1, t2,.. ,tn.
- Dòng thứ 3 ghi N-1 số nguyên dương r1, r2,.. ,rn-1.
Kết quả: Ghi ra file văn bản TICK.OUT.
- Dòng đầu tiên ghi tổng số thời gian phục 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 (nếu không có ai cần rời

15


khỏi hàng thì quy ước ghi một số 0).
Ví dụ:

Hướng dẫn:
- Xét cấu hình x1, x2, x3, …, xn; Với xi=1 nếu người thứ i có nhờ người đứng trước
mua vé hộ và xi=0 nếu người thứ i không nhờ người đứng trước để mua.

- Time[i] là thời gian cần thiết để mua vé cho i người đầu tiên.
- Min là thời gian nhỏ nhất để mua vé cho tất cả mọi người.
- Luu để truy vết xem những khách hàng nào nhờ mua vé.
- Khi đó ta có thể giải bài toán bằng cách liệt kê tất cả các dãy bít độ dài n không có 2
bit 1 liền nhau. Tương ứng với mỗi dãy bit như vậy là 1 phương án. Trong số các
phương án đó ta tìm ra một phương án tối ưu (có tổng thời gian nhỏ nhất).
const fi='Tick.INP';
fo='Tick.OUT';
var f:text;
t,x,r,s,l:array[0..1000000] of longint;
n,i,min:longint;
{==============================}
procedure mv(i:longint);
var j:longint;
begin
if x[i-1]=0 then
for j:=0 to 1 do
begin
x[i]:=j;
if x[i]=0 then
s[i]:=s[i-1]+t[i]
else
s[i]:=s[i-1]+r[i-1]-t[i-1];
if i=n then
begin
if s[n]begin
min:=s[n];
l:=x;
end;

end
else
if s[i]mv(i+1);
end
else
begin
x[i]:=0;
s[i]:=s[i-1]+t[i];
if i=n then
begin
if s[n]begin
min:=s[n];
l:=x;
16


end;
end
else
if s[i]mv(i+1);
end;
end;
{============================}
BEGIN
assign(f,fi);
reset(f);
readln(f,n);

min:=0;
for i:=1 to n do
begin
read(f,t[i]);
min:=min+t[i];
end;
for i:=1 to n-1 do
read(f,r[i]);
x[0]:=1;
MV(1);
assign(f,fo);
rewrite(f);
writeln(f,min);
for i:=1 to n do
if x[i]=1 then
write(f,i,' ');
close(f);
END.

Bài số 13: Chèn xâu
Đề thi chọn HSG tỉnh Vĩnh Long 2009
Cho xâu S = ’123456789’ hãy tìm cách chèn vào S các dấu '+' hoặc '-' để thu được
biểu thức có giá trị bằng số nguyên M cho trước (nếu có thể).
Dữ liệu vào trong file CHENXAU.INP gồm một số nguyên M.
Dữ liệu ra ghi vào file văn bản CHENXAU.OUT tất cả các phương án chèn (nếu có) và ghi
Khong co nếu như không thể thu được M từ cách làm trên.
Ví dụ:
CHENXAU.INP
CHENXAU.OUT
500

1-234-56+789
1-2+345+67+89
-12+34+567-89
1000
Khong co
Hướng dẫn:
- Dùng cấu hình d1, d2, …, d9 để xác định dấu trước các chữ số
+ di=-1 nếu trước chữ số i là dấu –
+ di=0 nếu trước chữ số i không có dấu
+ di=1 nếu trước chữ số i là dấu +
- Viết hàm tính tổng các số trong xâu S. Hàm này được tính dựa vào xâu S và dãy d1,
d2, .., d9

17


-

Hàm SO(k) lấy số trong xâu S bắt đầu từ chữ số k
(hàm này dựa vào S và dãy d1, d2, …, d9)

const fi='chenxau.inp';
fo='chenxau.out';
var f:text;
m,d:longint;
s:string[9];
x:array[1..9] of longint;
{=======================}
function so(i:longint):longint;
var st:string[10];

k,code:integer;
begin
st:=s[i];
for k:=i+1 to 9 do
if x[k]=0 then
st:=st+s[k]
else
break;
val(st,so,code);
end;
{========================}
Procedure Chen(i:longint);
var j,k,t:longint;
begin
for j:=0 to 2 do
begin
x[i]:=j;
if i=9 then
begin
if x[1]=1 then
t:=-so(1)
else
t:=so(1);
for k:=2 to 9 do
if x[k]<>0 then
if x[k]=1 then
t:=t-so(k)
else
t:=t+so(k);
if (t=M) and (x[1]<>2) then

begin
d:=1;
if x[1]=1 then
write(f,'-',so(1))
else
write(f,so(1));
for k:=2 to 9 do
if x[k]<>0 then
if x[k]=1 then
write(f,'-',so(k))
else
write(f,'+',so(k));
writeln(f);
end;
end
else
Chen(i+1);
18


end;
end;
{==================================}
BEGIN
assign(f,fi);
reset(f);
readln(f,M);
s:='123456789';
assign(f,fo);
rewrite(f);

Chen(1);
if d=0 then
write(f,'KHONG');
close(f);
END.

Bài số 14: Đổi tiền
Một ngân hàng có N loại tiền, mệnh giá lần lượt là t[1], t[2], ..., t[n], loại tiền mệnh giá
t[i] có số tờ tương ứng là m[i]. Cần trả cho khách hàng một khoản tiền S, hãy cho biết cần sử
dụng bao nhiêu tờ mỗi loại để số tờ chi trả là ít nhất.
Dữ liệu: Vào từ tệp văn bản DOITIEN.INP:
- Dòng đầu ghi S và N
- N dòng tiếp theo mỗi dòng ghi 2 số lần lượt là t[i] và m[i].
Kết quả: Ghi ra tệp văn bản DOITIEN.OUT
- Ghi -1 nếu không thể trả khoản tiền S
- Nếu trả được: Dòng đầu ghi số tờ ít nhất phải trả; dòng thứ 2 ghi mệnh giá và số tờ của
các loại tiền đã dùng để chi trả.
Ví dụ:
DOITIEN.INP
DOITIEN.OUT
100 5
10
9 10
9:6 2:1 4:1 20:2
2 18
4 16
1 13
20 2
Hướng dẫn:
- Cấu hình (x1, x2, ..., xn) trong đó: x[i] là số tờ của loại tiền mệnh giá t[i]

- X[i] nhận các giá trị từ 0 đến m[i]
- Dùng mảng Tong[1..N] để lưu kết quả mỗi bước.

Bài 15. MÁY RÚT TIỀN ATM
Sau một thời gian tìm kiếm. Cuối cùng Bờm cũng đã tìm được một công việc tại ngân
hàng KID Bank là ngân hàng mới được thành lập tại thị trấn. Một hôm nọ, Bờm được giám
đốc gọi lên và giao nhiệm vụ lập chương trình cho máy rút tiền tự động - ATM. Khổ nỗi, Bờm
chỉ được đào tạo về sửa chữa máy tính và những hư hỏng thông thường của máy PHOTO,
máy FAX và … lập trình PASCAL căn bản!.
19




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

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