Bài toán phép nhân tổ hợp dãy ma trận

Một phần của tài liệu ỨNG DỤNG PHƯƠNG PHÁP QUY HOẠCH ĐỘNG ĐỂ GIẢI CÁC BÀI TOÁN TỐI ƯU TỔ HỢP 10600755 (Trang 38 - 44)

5. Bố cục đề tài

2.3. Bài toán phép nhân tổ hợp dãy ma trận

2.3.1. Phát biểu bài toán

Cần tính M = M1 x M2 x … x Mn

Trong đó: Mi là ma trận cấp a[i – 1] x a[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.

Dữ liệu vào: Ghi vào tệp tin văn bản Matrix.inp gồm:

- Dòng đầu tiên ghi số lượng n ma trận (n <= 100).

- Dòng thứ hai ghi n + 1 số nguyên dương a[1], a[2], …, a[n + 1] cách nhau một khoảng trắng.

Dữ liệu ra: Ghi vào tệp tin văn bản Matrix.out gồm:

- Dòng đầu tiên ghi số phép nhân tối thiểu cần thực hiện.

- Dòng thứ hai ghi biểu thức kết hợp tối ưu của phép nhân dãy ma trận. Ví dụ: Matrix.inp Matrix.out 5 2 4 1 3 5 2 37 (m[1].m[2])((m[3].m[4]).m[5])

2.3.2. Phân tích, xử lý bài toán và lập hệ thức truy hồi

Theo ta biết, phép nhân ma trận không có tính chất giao hoán nhưng có tính chất kết hợp.

Nếu dãy chỉ có một ma trận thì số phép nhân là 0, và phép nhân một cặp ma trận có thể tính được ngay, bằng tích số hàng ma trận bên trái, số cột ma trận bên trái với số cột ma trận bên phải.

Ví dụ 1:

Phép nhân hai ma trận A x B với A cấp 3 x 5, B cấp 5 x 4 tạo thành ma trận cấp 3 x 4 với số phép nhân là 3 x 5 x 4 = 60.

Tiếp tục như vậy, ta sẽ tính được số phép nhân của dãy ba ma trận liên tiếp… Cuối cùng thì tính được số phép nhân của n ma trận.

Ví dụ 2:

Phép nhân hai ma trận A x B x C với A cấp 3 x 6, B cấp 6 x 4 và C cấp 4 x 7: Với cách kết hợp (A x B) x C. Phép tính A x B tạo thành ma trận cấp 3 x 4 với số phép nhân là 3 x 6 x 4 = 72, sau đó nhân tiếp với ma trận C tạo thành ma trận cấp 3 x 7 với số phép nhân là 3 x 4 x 7 = 84. Tổng số phép nhân là 156. Với cách kết hợp A x (B x C). Phép tính B x C tạo thành ma trận cấp 6 x 7 với số phép nhân là 6 x 4 x 7 = 168, sau đó được nhân bởi ma trận A tạo thành ma trận 3 x 7 với số phép nhân là 3 x 6 x 7 = 126. Tổng số phép là 294.

Với ví dụ trên, ta thấy rằng tùy thuộc vào cách kết hợp mà được số phép nhân tối thiểu.

Gọi f[i, j] là số phép nhân tối thiểu cần thực hiện để nhân đoạn ma trận liên tiếp từ i đến j. Khi đó f[i, i] = 0 i.

Gọi k là vị trí xen giữa i và j (i ≤ k ≤ j).

Để tính f[i, j] thì có nhiều cách kết hợp, tương ứng với một giá trị k là một trong các cách đó:

f[i, j] = f[i, k] + f[k, j] + a[i].a[k + 1].a[j +1]

Với a[i].a[k + 1].a[j + 1] là số phép nhân của tích các ma trận từ i đến k và các ma trận từ k + 1 đến j.

Suy ra, do có nhiều cách kết hợp, ta cần chọn cách kết hợp để đạt số phép nhân ít nhất:

f[i, j] = min i ≤ k ≤ j (f[i, k] + f[k, j] + a[i].a[k + 1].a[j +1])

2.3.3. Thuật toán

Khởi tạo mảng một chiều có độ dài n + 1 và các giá trị của mảng lần lượt là các số được đọc vào từ file đầu vào.

Khởi tạo mảng hai chiều có số dòng và số cột là n + 1 dùng để lưu trữ các giá trị k (vị trí cần kết hợp).

Khởi tạo mảng hai chiều có số dòng và số cột là n:

- Đối với các phần tử nằm trên đường chéo chính (1, 1), (2, 2)… (n, n) khởi tạo với giá trị là 0.

f[i, j] = min i ≤ k ≤ j (f[i, k] + f[k, j] + a[i].a[k + 1].a[j +1]) + Bắt đầu từ các phần tử ở vị trí số cột = số hàng + 1.

+ Tiếp tục là các phần tử ở vị trí số cột = số hàng + 2. …

+ Cuối cùng, là phần tử ở vị trí (1, n).

Tại trường hợp min, lưu trữ giá trị k vào đúng vị trí của phần tử đó ở mảng hai chiều đầu tiên vừa tạo ở trên.

Truy vết, sử dụng thuật toán đệ quy trên mảng hai chiều đầu tiên (lưu trữ giá trị k) để ghi biểu thức kết hợp tối ưu của phép nhân dãy ma trận.

2.3.4. Thiết kế chương trình

B1: Khởi tạo mảng size một chiều có độ dài n + 1 và các giá trị của mảng

lần lượt là các số được đọc vào từ file Matrix.inp.

B2: Khởi tạo mảng position hai chiều có số dòng và số cột là n. B3: Khởi tạo mảng matrix hai chiều có số dòng và số cột là n:

- Các phần tử ở vị trí (1, 1), (2, 2)… (n, n) được khởi tạo giá trị là 0. - Các phần tử nằm ở vị trí số hàng < số cột được tính như sau:

For len từ 1 đến n - 1

For i từ 1 đến khi i + len = n

j = i + len

leftMatrix = matrix[i][k] rightMatrix = matrix[k + 1][j] tmp = leftMatrix + rightMatrix + size[i].size[k+1].size[j + 1] If matrix[i][j] > tmp matrix[i][j] = tmp position[i][j] = k

B4: Truy vết, sử dụng thuật toán đệ quy theo phần tử (1, n) thuộc mảng position.

If i = j

Ghi mi vào file Matrix.out

Else

k = position[i][j]

Ghi dấu ( vào file Matrix.out Đệ quy theo phần tử (i, k) Ghi dấu . vào file Matrix.out Đệ quy theo phần tử (k + 1, j) Ghi dấu ) vào file Matrix.out

2.3.5. Ví dụ

Khởi tạo mảng matrix gồm 5 dòng, 5 cột với:

- Các phần tử (1, 1), (2, 2), (3, 3), (4, 4), (5, 5) được khởi tạo giá trị là 0. - Các phần tử còn lại được tính theo công thức:

f[i, j] = min i ≤ k ≤ j (f[i, k] + f[k, j] + a[i].a[k + 1].a[j +1])

Từ đó, ta được mảng position như sau:

0 1 2 3 4 5 1 0 8 14 33 37 2 0 12 35 33 3 0 15 25 4 0 30 5 0 0 1 2 3 4 5 1 0 1 2 2 2 2 0 2 2 2 3 0 3 4 4 0 4 5 0

Đệ quy theo phần tử (1, 5) để ghi biểu thức kết hợp tối ưu của phép nhân dãy ma trận:

- Vì 1 ≠ 5 => k = 2, tiếp tục đệ quy theo hai phần tử (1, 2) và (3, 5). + Vì 1 ≠ 2 => k = 1, ghi nhận được phần tử (1, 1) và (2, 2).

+ Vì 3 ≠ 5 => k = 4, tiếp tục đệ quy theo phần tử (3, 4) và ghi nhận phần tử (5, 5).

++ Vì 3 ≠ 4 => k = 1, ghi nhận được phần tử (3, 3) và (4, 4). => Biểu thức tối ưu: (m[1].m[2])((m[3].m[4]).m[5])

Một phần của tài liệu ỨNG DỤNG PHƯƠNG PHÁP QUY HOẠCH ĐỘNG ĐỂ GIẢI CÁC BÀI TOÁN TỐI ƯU TỔ HỢP 10600755 (Trang 38 - 44)

Tải bản đầy đủ (PDF)

(70 trang)