Tuyển tập một số bài tập quy hoạch động bồi dưỡng học sinh giỏi tin học THPT. Trong tài liệu này đưa ra một số dạng quy hoạch động thường gặp trong đề thi, có chương trình đi kèm,Một số bài toán: Xếp hàng mua vé; Di chuyển trên mảng 2 chiều; di chuyển trên bảng tam giác; bài toán chia quà...
Trang 1TUYỂN TẬP 1 SỐ BÀI TẬP QUY HOẠCH ĐỘNG VÀ LỜI GIẢI
Bài 1: Xếp hàng mua vé
N người có số hiệu từ 1 đến N xếp hàng mua vé Người có số hiệu bé hơn xếp trước và mua vé trước Mỗi người được mua 1 vé cho mình và có thể mua hộ vé cho người đứng sau đó Người có số hiệu I khi mua vé cho mình và cho người đứng sau thì mất Rk phút (1<=k<=n)
Hãy sắp xếp bố trí xem người nào cần ở lại mua vé, người nào cần rời khỏi hàng để nhờ người đứng trước mua hộ sao cho tổng thời gian mua là ít nhất
Dữ liệu vào
- Dòng đầu chứa số nguyên dương N
- Dòng tiếp theo ghi N số nguyên dương Ti
- Dòng tiếp theo ghi N-1 số nguyên dương Rk
Dữ liệu ra
- Dòng đầu ghi tổng thời gian bán ít nhất
- Dòng thứ 2 ghi chỉ số những người ở lại hàng mua vé
4
3 2 4 3
4 3 7
9
4 2 1
var
t,r,f:array[0 1000] of longint;
kt:array[1 1000] of boolean;
n,k,i:longint;
fi,fo:text;
procedure enter;
begin
assign(fi,'MUAVE.INP');
reset(fi);
readln(fi,n);
for i:=1 to n do read(fi,t[i]);
readln(fi);
for i:=1 to n-1 do read(fi,r[i]);
close(fi);
end;
procedure result;
begin
assign(fo,'MUAVE.OUT');
rewrite(fo);
writeln(fo,f[n]);
for i:=1 to n do if kt[i] then write(fo,i,' ');
close(fo);
end;
procedure main;
begin
fillchar(kt,n,true);
r[0]:=0;
f[0]:=0;
Trang 2f[1]:=t[1];
for i:=2 to n do
if f[i-1]+t[i]>f[i-2]+r[i-1] then
begin
kt[i]:=false;
kt[i-1]:=true;
f[i]:=f[i-2]+r[i-1];
end
else f[i]:=f[i-1]+t[i];
end;
begin
enter;
main;
result;
end.
Bài 2: Đường đi của Robot
Cho ma trận vuông cấp N Mỗi ô ghi 1 số nguyên bất kỳ Tìm đường đi của robot từ ô (1,1) đến ô (N,N) sao cho tổng các số trên đường đi là nhỏ nhất Biết rằng robot chỉ có thể di chuyển qua các ô kề cạnh, sang phải hoặc xuống dưới so với ô đang đứng
3
27
1 1
2 1
2 2
2 3
3 3
var
a,b:array[0 1000,0 1000] of longint;
m,n:longword;
fi,fo:text;
procedure enter;
var i,j:integer;
begin
assign(fi,'ROBOT.INP');
reset(fi);
readln(fi,m,n);
for i:=1 to m do
begin
for j:=1 to n do read(fi,a[i,j]);
readln(fi);
end;
for i:=1 to m do b[1,i]:=a[1,i];
for i:=1 to n do b[i,1]:=a[i,1];
close(fi);
end;
procedure result;
Trang 3var
i,j,k:integer;
ii:array[1 10000] of longint;
jj:array[1 10000] of longint;
begin
assign(fo,'ROBOT.OUT');
rewrite(fo);
writeln(fo,b[m,n]);
i:=m;
j:=n;
k:=0;
while (i>1) or (j>1) do
begin
inc(k);
ii[k]:=i;
jj[k]:=j;
if b[i,j]=a[i,j]+b[i-1,j] then dec(i);
if b[i,j]=a[i,j]+b[i,j-1] then dec(j);
end;
writeln(fo,1,' ',1);
for i:=k downto 1 do writeln(fo,ii[i],' ',jj[i]);
close(fo);
end;
procedure main;
var
i,j:longint;
begin
b[1,1]:=a[1,1];
for i:=2 to m do
for j:=2 to n do
if (i<>1) or (j<>1) then
if b[i-1,j]>b[i,j-1] then b[i,j]:=b[i-1,j]+a[i,j]
else b[i,j]:=a[i,j]+b[i,j-1];
end;
begin
enter;
main;
result;
end.
Bài 3: Sa mạc
Sa mạc là lưới ô vuông cấp M x N Trên mỗi ô lưới người ta ghi 1 số nguyên a gọi là năng lượng của ô đó Một con lạc đà đi từ ô (1,1) đến ô (m,n) Tìm đường đi sao cho đường đi của lạc đà có tổng lớn nhất Biết rằng lạc đà chỉ đi sang 2 ô (i+1,j) hoặc (I,j+1)
4 5
1 5 1 3 4
41
1 1
Trang 46 7 9 1 5
1 1 8 4 1
1 3 4 3 3
2 1
2 2
2 3
3 3
3 4
4 4
4 5
Bài 4: Đường đi
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
Là một bảng tam giác các số nguyên không âm Viết chương trình tính tổng lớn nhất các
số trên đường đi từ đỉnh xuông đáy tam giác Mỗi bước đi ta được quyền đi thằng xuống dưới bên trái hoặc bên phải số đó
program dd_tamgiac;
const fi='tamgiac.inp';
fo='tamgiac.out';
nmax=100;
var f:text;
n,tong:integer;
a:array[1 nmax,1 nmax] of integer;
l:array[1 nmax,0 nmax] of integer;
procedure doc;
var i,j:integer;
begin
assign(f,fi);
reset(f);
readln(f,n);
for i:=1 to n do
begin
for j:=1 to i do
read(f,a[i,j]);
readln(f);
end;
end;
function max(x,y:integer):integer;
begin
if x>y then max:=x
else max:=y;
end;
Trang 5procedure qhd;
var i,j:integer;
begin
l[1,0]:= low(integer);
l[1,1]:=a[1,1];
for i:=2 to n do
for j:=1 to i do
l[i,j]:=a[i,j]+max(l[i-1,j-1],l[i-1,j]);
tong:=l[n,1];
for i:=2 to n do
if tong<l[n,i] then tong:=l[n,i];
end;
begin
doc;
qhd;
writeln(tong);
readln;
end.
Bài 5: Cho bàn cờ hình chữ nhật kích thước M,N Robot đứng tại ô trên trái của
bàn cờ Robot có thể di chuyển sang ô kề bên phải hoặc xuống dưới Tình xem có bao nhiêu cách di chuyển robot xuống ô dưới phải của bàn cờ
Dữ liệu vào là kích thước bàn cờ (0<M,N<10)
Dữ liệu ra là số cách di chuyển
program so_cach_dichuyen;
const fi='banco.inp';
fo='banco.out';
nmax=10;
var f:text;
m,n:integer;
l:array[1 nmax,1 nmax] of integer;
procedure doc;
begin
assign(f,fi);
reset(f);
readln(f,m,n);
end;
procedure qhd;
var i,j:integer;
begin
for i:=1 to m do l[i,1]:=1;
for i:=1 to n do l[1,i]:=1;
for i:=2 to m do
for j:=2 to n do
l[i,j]:=l[i-1,j]+l[i,j-1];
Trang 6writeln(l[m,n]);
end;
begin
doc;
qhd;
readln;
end.
Bài 6: Quà tết trung thu
Cho bảng hình chữ nhật kích thước M,N Trêm mỗi ô ghi 1 số nguyên dương Có thể di chuyển từ một ô sang ô thuộc cột bên phải cùng dòng hoặc chênh lệch 1 dòng.Tìm cách di chuyển từ 1 ô nào đó thuộc cột bên trái sang ô thuộc cột N sao cho tổng món quà nhận được là lớn nhất
3 5
7 3 8 1 5
8 8 3 12 1
6 15 10 5 2
50
2 3 3 2 1 (Chỉ số dòng các ô đi qua từ cột 1 đến cột N)
program qua_tet;
const fi='quatet.inp';
fo='quatet.out';
nmax=100;
var f:text;
a:array[1 nmax,1 nmax] of integer;
b:array[0 nmax,0 nmax] of integer;
i,m,n,tong,cs,dem:integer;
h:array[1 nmax] of integer;
procedure doc;
var i,j:integer;
begin
assign(f,fi);
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;
end;
function max(x,y,z:integer):integer;
begin
max:=x;
if max<y then max:=y;
if max<z then max:=z;
end;
procedure qhd;
Trang 7var i,j:integer;
begin
for i:=1 to m do b[i,1]:=a[i,1];
for j:=2 to n do
for i:=1 to m do
b[i,j]:=a[i,j]+ max(b[i,j-1],b[i-1,j-1],b[i+1,j-1]); end;
procedure truy;
var i,j:integer;
begin
cs:=1;
dem:=1;
for i:=2 to m do
if b[i,n]>b[cs,n] then cs:=i;
tong:=b[cs,n];
j:=n;
i:=cs;
h[dem]:=cs;
while j<>1 do
begin
inc(dem);
if b[i,j]=b[i,j-1]+a[i,j] then h[dem]:=i
else
if b[i,j]=b[i-1,j-1]+a[i,j] then
begin
h[dem]:=i-1;
dec(i);
end
else
begin
h[dem]:=i+1;
inc(i);
end;
dec(j);
end;
end;
begin
doc;
qhd;
truy;
writeln(tong);
for i:=n downto 1 do write(h[i],' ');
readln;
end.
Trang 8Bài 7: Cho bảng hai chiều M,N Mỗi ô vuông chứa 1 số nguyên Tìm trong bảng
hình chữ nhật có tổng các số trên ô là lớn nhất
4 4
0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 2 152 1 4 2
program hinhchunhat;
const fi='hcn.inp';
fo='hcn.out';
nmax=100;
var a:array[1 nmax,1 nmax] of integer;
m,n,max,hang1,hang2,cot1,cot2:integer;
f:text;
b:array[0 nmax,0 nmax] of integer;
procedure doc;
var i,j:integer;
begin
assign(f,fi);
reset(f);
readln(f,m,n);
for i:=1 to m do
for j:=1 to n do
read(f,a[i,j]);
end;
function dt(x,y:integer):integer;
var s,i,j:integer;
begin
s:=0;
for i:=1 to x do
for j:=1 to y do
s:=s+a[i,j];
dt:=s;
end;
procedure qhd;
var i,j:integer;
begin
for i:=1 to m do
for j:=1 to n do
b[i,j]:=dt(i,j);
end;
function dtich(h1,c1,h2,c2:integer):integer;
begin
dtich:=b[h2,c2]-b[h1-1,c2]-b[h2,c1-1]+b[h1-1,c1-1];
end;
procedure timmax;
var x,y,z,k:integer;
begin
max:=low(integer);
Trang 9for x:=1 to m do
for y:=1 to n do
for z:=x to m do
for k:=y to n do
if max<dtich(x,y,z,k) then
begin
max:=dtich(x,y,z,k);
hang1:=x;
hang2:=z;
cot1:=y;
cot2:=k;
end;
end;
begin
doc;
qhd;
timmax;
writeln(max);
writeln(hang1,' ',cot1,' ',hang2,' ',cot2); readln;
end.