Phát biểu bài toán: Một cái kho chứa n loại đồ vật có kích thước và giá trị khác nhau. Cụ thể: Loại đồ vật i (i=1..n) có: kích cỡ m[i]∈ N*; gía trị c[i] ∈R; số lượng:
không hạn chế
Một tên trộm mang theo chiếc túi có kích cỡ là p∈N*. Vậy hắn phải chọn lựa một danh sách các đồ vật sẽ mang đi như thế nào để cho tổng giá trị lấy cắp được là lớn nhất.
Tức: Tìm x[1], x[2],..., x[n] (với x[i]∈ N : số lượng loại đồ vật thứ i cần lấy) sao cho:∑x[i].m[i] ≤p và∑x[i].c[i] đạt giá trị cực đại.
Input:Một cái túi chứa n loại đồ vật có kích thước và giá trị khác nhau.
Cụ thể: Loại đồ vật i (i=1..n) có:
- Kích cỡ m[i] ∈N*
- Giá trị c[i]∈R
- Số lượng: không hạn chế
Có thể biểu diễn dữ liệu vào thông qua bảng như sau:
Loại đồ vật i 1 2 ... n
Kích cỡ M[i] M[1] M[2] ... M[n] N*
Giá trị C[i] C[1] C[2] ... C[n] R
Số lượng các loại đồ vật không hạn chế.
p∈N* là kích cỡ chiếc túi
(Một tên trộm mang theo chiếc túi có kích cỡ là p∈ N*. Vậy hắn phải chọn lựa một danh sách các đồ vật sẽ mang đi như thế nào để cho tổng giá trị lấy cắp được là lớn nhất.)
Output: Tìm x[1], x[2],..., x[n] (với x[i] ∈ N: số lượng loại đồ vật thứ i cần lấy) sao cho:Σx[i].m[i] ≤p vàΣx[i].c[i] đạt giá trị cực đại.
2. Phương pháp thực hiện, sử dụng phương pháp quy hoạch động với 4 bước là:
Bước 1: Phân tích bài toán
- Gọi P(r, s) là bài toán chiếc túi xách, với:
r∈N*: kích cỡ chiếc túi
s∈N*: số các loại đồ vật khác nhau
=>bài toán ban đầu là P(p, n) - Các giá trị cần tìm:
l[r,s]: giá trị cực đại ∑x[i].c[i] của bài toán P(r, s)
u[r,s]: số lượng loại đồ vật s tối ưu cần lấy (tức: x[s]) của bài toán P(r, s)
Bước 2: Xây dựng giải pháp đệ quy - Trường hợp chung: s > 1
l[r, s] = max { k∗c[s] + l[r – k∗m[s], s-1] } (1) (0≤k≤r div m[s])
= k’∗c[s] + l[r – k’∗m[s], s-1]
u[r, s] = k’
- Trường hợp suy biến: s = 1 u[r, 1] = r div m[1]
l[r, 1] = u[r, 1]∗c[1]
{(1) có nghĩa là: + k∗c[s] là giá trị mang lại khi lấy k đồ vật thứ s, + r – k∗m[s] kích thước của cái túi giảm đi k∗m[s], + (s - 1) số loại đồ vật giảm đi 1
bài toán lớn được tính thông qua bài toán nhỏ hơn}
Bước 3: Lập bảng Procedure LapBang;
Begin
For s:=1 to n do For r:=0 to p do
If s=1 then Tính u[r, 1] và l[r, 1]
else Tính u[r, s] và l[r, s];
End;
Độ phức tạp tính toán là: O(np2) Bước 4: Tổng hợp kết quả Procedure TongHop;
Begin r:=p;
For s:=n downto 1 do Begin
x[s]:= u[r,s];
r:= r – x[s].m[s];
End;
End;
Độ phức tạp tính toán: O(n)
CODE BÀI TOÁN CHIẾC TÚI XÁCH Dữ liệu vào được lưu trong file Input.txtgồm 2 dòng:
+ Dòng đầu là số nguyên n (số đồ vật) và p (cỡ của túi xách) + Dòng i+1 (1<=i<=n) ghi 2 số nguyên dương m[i], c[i].
program BT_CTX;
const input = 'input.txt';
nmax = 100;
pmax = 100;
var u,l: array[1..pmax,1..nmax] of integer;
m,c, x: array[1..nmax] of integer;
i,n,p: integer;
procedure Doc_DL;
var f: text;
i: integer;
begin
Assign(f,input);
Reset(f);
readln(f,n,p);
for i:=1 to n do readln(f,m[i],c[i]);
close(f);
end;
procedure Lap_Bang;
var r, s, k, k1, tam, max : integer;
begin
for s:=1 to n do for r:=0 to p do
if s= 1 then begin
u[r,1]:= r div m[1];
l[r,1]:=u[r,1] * c[1];
end else
begin
k1:= 0;
max:= l[r,s-1];
for k:=1 to r div m[s] do begin
tam:= k*c[s] + l[r-k*m[s],s-1];
if tam > Max then begin
max:=tam;
k1:=k;
end;
end;
l[r,s]:=max;
u[r,s]:=k1;
end;
end;
Procedure TongHop_KQ;
var r,s: integer;
begin r:=p;
for s:=n downto 1 do begin
x[s]:= u[r,s];
r:=r- x[s]*m[s];
end;
for s:=1 to n do
writeln('Do vat ', s, ' can lay ', x[s], ' cai');
writeln('Gia tri toi uu: ', l[p,n]);
end;
begin
Doc_DL;
Lap_Bang;
TongHop_KQ;
readln;
end.
Kết quả chạy thử Dữ liệu đầu vào:
5 8 2 3 1 4 2 5 4 5 1 5
Dữ liệu đầu vào:
2 8 2 3 3 4
Dữ liệu đầu vào:
7 15 2 3 3 4 2 5 4 5 8 5 4 7 3 6 Kết quả:
Do vat 1 lay 0 cai Do vat 2 lay 0 cai Do vat 3 lay 0 cai Do vat 4 lay 0 cai Do vat 5 lay 8 cai Gia tri toi uu : 40
Kết quả:
Do vat 1 lay 4 cai Do vat 2 lay 0 cai Gia tri toi uu : 12
Kết quả:
Do vat 1 lay 0 cai Do vat 2 lay 0 cai Do vat 3 lay 6 cai Do vat 4 lay 0 cai Do vat 5 lay 0 cai Do vat 6 lay 0 cai Do vat 7 lay 1 cai Gia tri toi uu : 36
Bài tập 10 : Bài toán phép nhân tổ hợp nhiều ma trận 1. Phát biểu bài toán:
Cần tớnh M = M1ìM2ì...ìMn
Trong đú: Milà ma trận cấp m[i-1]ìm[i] (i=1..n)
Hãy xác định thứ tự thực hiện các phép nhân sao cho số phép tính là tối thiểu.
Cần tớnh M = M1ìM2ì...ìMn, trong đú: Mi là ma trận cấp m[i-1]ìm[i] (i=1..n), thể hiện điều này thông qua bảng sau, đây cũng chính là thông tin vào của bài toán.
Input: mảng m[i], i = 0..n
n: số các ma trận Cấp của các ma trận
I 0 1 ... n
m[i] m[0] m[1] ... m[n]
Output: Hãy xác định thứ tự thực hiện các phép nhân sao cho số phép tính là tối thiểu?
CODE PHÉP NHÂN TỔ HỢP NHIỀU MA TRẬN Program NhanMT;
const input = 'input.txt';
max = 100;
var l,k: array[1..max,1..max] of integer;
m,x: array[0..max] of integer;
n: integer;
Procedure Doc_DL;
var f: text;
i: integer;
begin
assign(f,input);
reset(f);
readln(f,n);
for i:=0 to n do readln(f,m[i]);
close(f);
end;
procedure LapBang;
var r,s, v,v1,tam, min: integer;
begin
for s:=1 to n do for r:=s downto 1 do
if r= s then l[r,s]:= 0 else
begin
v1:=r;
min:= l[r+1,s]+m[r-1]*m[r]*m[s];
for v:=r to s-1 do begin
tam:= l[r,v]+l[v+1,s]+m[r-1]*m[v]*m[s];
if tam < min then begin
min:=tam;
v1:=v;
end;
end;
l[r,s]:= min;
k[r,s]:= v1;
end;
end;
procedure TongHop_KQ;
var i: integer;
procedure TimVT(r,s: integer);
var vt: integer;
begin
if r<s then begin
i:=i-1;
vt:=k[r,s];
x[i]:=vt;
TimVT(r,vt);
TimVT(vt+1,s);
end;
end;
Begin
writeln('So phep tinh toi thieu: ', l[1,n]);
writeln('---');
i:=n;
TimVT(1,n);
for i:=1 to n-1 do writeln('Lan thu ',i, ' thuc hien phep toan thu ', x[i]:4);
End;
begin
Doc_DL;
LapBang;
TongHop_KQ;
readln;
end.
Kết quả chạy thử Dữ liệu đầu vào:
3 10 20 50 5
Dữ liệu đầu vào:
4 10 20 50 5 10 Kết quả:
So phep tinh toi thieu: 6000 --- Lan thu 1 thuc hien phep toan thu 2
Lan thu 2 thuc hien phep toan thu 1
Kết quả:
So phep tinh toi thieu: 6500 --- Lan thu 1 thuc hien phep toan thu 2
Lan thu 2 thuc hien phep toan thu 1
Lan thu 3 thuc hien phep toan thu 3
Bài tập 11 : Bài toán xâu cực đại 1. Phát biểu bài toán:
Định nghĩa xâu trong: S là xâu trong của T nếu S nhận được bằng cách xoá đi một số ký tự nào đó của T. Ví dụ: ‘ABC’ là xâu trong của ‘GAHEBOOC’ bằng cách xóa đi các ký tự GHEOO của xâu ‘GAHEBOOC’.
Bài toán: Cho 2 xâu T1, T2. Tìm một xâu S là xâu trong chung của T1 và T2 có độ dài cực đại.
Ví dụ: T1=‘ABCDAE’ và T2=‘XYACADK’ có xâu ‘ACD’ là xâu trong chung với độ dài cực đại.
Input: Xâu T1 và xâu T2
Output: XTCCĐ(T1, T2)
2.2.PhPhươươnnggphphááppththựựcchihiệệnn,,sửsửddụnụnggphphưươơnnggphphááppqquuyyhohoạạcchhđộđộnnggvớvớii44bbướướccllàà:: Bước 1: Phân tích bài toán
- Gọi P(r,s) là bài toán xâu trong cực đại, với:
r: là số ký tự đầu tiên của xâu T1 s: là số ký tự đầu tiên của xâu T2
Ví dụ : T1=‘x1x2…xr…xm’ (m=length(T1)) T2=‘y1y2…ys…yn’ (n=length(T2))
⇒Bài toán ban đầu: P (m,n) - Giá trị cần tìm:
l[r,s] : độ dài xâu trong chung cực đại của bài toán P (r,s) Bước 2: Giải pháp đệ quy
F[r,s] = F[r-1,s-1] + 1 Nếu r>0, s>0 và T1[r]=T2[s]
F[r,s] = max{F[r-1,s], F[r,s-1]} Nếu r>0, s>0 và T1[r]≠T2[s]
F[r,s] = 0 Nếu r=0 hoặc s=0
Bước 3: Lập bảng Procedure Lap_Bang;
var r,s: integer;
begin
m:= length(T1);
n:= length(T2);
for r:=0 to m do for s:=0 to n do
if (r=0) or (s=0) then F(r,s):=0 else
if T1[r] = T2[s] then F[r,s]:= F[r-1,s-1] + 1 else
F[r,s]:= max(F[r,s-1],F[r-1,s]);
end;
Độ phức tạp tính toán là: O(m*n) Bước 4: Tổng hợp kết quả procedure Tong_Hop_KQ;
var r, s: integer;
begin
St:='';
r:= m; s:= n;
Writeln('Do dai cuc dai cua xau trong chung la: ', F[r,s]);
while (r>0) and (s>0) do begin
if T1[r]= T2[s] then begin
St:= T1[r]+St;
r:= r-1;
s:= s-1;
end else
if F[r-1,s] > F[r,s-1] then r:=r-1 else
s:=s-1;
end;
Write('Xau trong chung cuc dai la: ',St);
writeln;
end;
Độ phức tạp tính toán: O(m*n)
CODE TÌM XÂU TRONG CHUNG CỰC ĐẠI Program Xau_Trong_Max;
uses crt;
const xau = 'xauchung.txt';
nMax = 100;
var F: array[0..nMax,0..nMax] of integer;
T1,T2,St: String;
m,n: integer;
procedure Doc_DL;
var fi:text;
begin
assign(fi,xau);
reset(fi);
readln(fi,T1);
readln(fi,T2);
close(fi);
m:= length(T1);
n:= length(T2);
end;
Function max(var a, b: integer): integer;
begin
if a>b then max:=a else
max:=b;
end;
Procedure Lap_Bang;
var r,s: integer;
begin
for r:=0 to m do for s:=0 to n do
if (r=0) or (s=0) then F(r,s):=0 else
if T1[r] = T2[s] then F[r,s]:= F[r-1,s-1] + 1 else
F[r,s]:= max(F[r,s-1],F[r-1,s]);
end;
procedure Tong_Hop;
var r, s: integer;
begin
St:=’’;
r:=m; s:=n;
Writeln('Do dai cuc dai cua xau trong chung la: ', F[r,s]);
while (r>0) and (s>0) do begin
if T1[r]= T2[s] then begin
St:= T1[r]+St;
r:= r-1;
s:= s-1;
end else
if F[r-1,s] > F[r,s-1] then r:=r-1 else
s:=s-1;
end;
Write('Xau trong chung cuc dai la: ',St);
writeln;
end;
begin
Doc_DL;
writeln('Xau X: ', T1);
writeln('Xau Y: ',T2);
writeln('---');
Lap_Bang;
Tong_Hop;
readln;
end.
Kết quả chạy thử Dữ liệu đầu vào:
ABCDAE XYACADKE
Dữ liệu đầu vào:
DINHVU NINHCU Kết quả:
Xau X: ABCDAE Xau Y: XYACADKE
--- Do dai cuc dai cua xau trong chung la: 4 Xau trong chung cuc dai la: ACAE
Kết quả:
Xau X: DINHVU Xau Y: NINHCU
--- Do dai cuc dai cua xau trong chung la: 4 Xau trong chung cuc dai la: INHU Bài tập 12 : Bài toán du lịch
1. Phát biểu bài toán:
Một người đi từ thành phố 0 đến thành phố n và có thể đi qua n-1 thành phố khác 1, 2,..., n-1, theo lộ trình: 0→i1→i2 …..→ik→n, trong đó: 0 < i1 < i2 < …<
ik < n. Giá vé của xe đi từ thành phố i đến thành phố j là c[i,j].
Tìm một lộ trình từ thành phố 0 đến thành phố n sao cho tổng chi phí về giá vé đạt cực tiểu.
Input:
+ n: số thành phố tối đa có thể đi qua.
+ c[i,j]: Ma trận chi phí trong đó c[i,j] là chi phí trực tiếp để đi từ thành phố i đến thành phố j (nếu i và j có đường đi trực tiếp). Nếu không có đường đi trực tiếp đến c[i,j]=∞.
Output:
+ Chi phí nhỏ nhất đến từ thành phố 0 đến thành phố n.
+ X[i]: số thứ tự thành phố đi qua.