Bài toán
Cho một ma trận biểu diễn bằng một mảng hai chiều kích thƣớc N x M ô và chỉ chứa các kí tự 0 và 1. Tìm hình chữ nhật chứa toàn kí tự 1 và có diện tích lớn nhất (gọi là hình chữ nhật tối đại) [2].
Phân tích bài toán
Tƣ̀ yêu cầu của bài toán ta xét mô ̣t số ví dụ sau: Ví dụ 1: Cho ma trâ ̣n 7 x 8 (Hình 2.6) 0 0 0 0 1 0 0 1 0 1 1 0 1 1 0 1 0 1 1 0 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 1 0 Hình 2.6: VD1 - Ma trận chứa các kí tự 0 và 1
Với ma trâ ̣n t rên ta tìm đƣợc hình chƣ̃ nhâ ̣t tối đa ̣i chƣ́a các kí tƣ̣ 1 có diện tích là 10 ô vuông và có toạ độ đỉnh trên - trái là (Cô ̣t 2, dòng 4) và đỉnh dƣới – phải là (cô ̣t 6, dòng 5)
0 0 0 0 1 0 0 1 0 1 1 0 1 1 0 1 0 1 1 0 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 0 0 1 0 0 0 0 0
26
0 0 1 0 0 1 1 0 Ví dụ 2:
Dƣ̣a vào ma trâ ̣n trên ta thay đổi giá tri ̣ 1 bằng giá tri ̣ 0 tại cột 4, dòng 4 (Hình 2.7). 0 0 0 0 1 0 0 1 0 1 1 0 1 1 0 1 0 1 1 0 0 1 0 1 0 1 1 0 1 1 0 1 1 1 1 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 1 0 Hình 2.7: VD2 - Ma trận chứa các kí tự 0 và 1
Lúc này ma trâ ̣n trên ta tìm đƣợc hình chƣ̃ nhâ ̣t tối đa ̣i chƣ́a các kí tƣ̣ 1 có diện tích là 8 ô vuông và có toạ độ đỉnh trên - trái là (Cô ̣t 2, dòng 2) và đỉnh dƣới – phải là (cô ̣t 3, dòng 5)
0 0 0 0 1 0 0 1 0 1 1 0 1 1 0 1 0 1 1 0 0 1 0 1 0 1 1 0 1 1 0 1 1 1 1 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 1 0 Ví dụ 3:
Tƣ̀ ma trâ ̣n của ví dụ 2 ta thay đổi giá tri ̣ 1 bằng giá tri ̣ 0 tại cột 3, dòng 4 (Hình 2.8)
0 0 0 0 1 0 0 1 0 1 1 0 1 1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 1 1 0 1
0 0 1 0 0 0 0 0 0 0 1 0 0 1 1 0
Hình 2.8: VD3 - Ma trận chứa các kí tự 0 và 1
Khi đó ma trâ ̣n trên ta tìm đƣợc hình chƣ̃ nhâ ̣t tối đa ̣i chƣ́a các kí tƣ̣ 1 có diện tích là 7 ô vuông và có toạ độ đỉnh trên - trái là (Cô ̣t 1, dòng 5) và đỉnh dƣới – phải là (cô ̣t 7, dòng 5).
0 0 0 0 1 0 0 1 0 1 1 0 1 1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 1 1 0 1 1 1 1 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 1 0
Tƣ̀ yêu cầu của bài toán và qua các ví dụ minh ho ̣a ta đƣa bài toán trên với dƣ̃ liê ̣u vào và ra nhƣ s au :
- Input: Tệp văn bản CNMAX.INP:
+ Dòng đầu tiên chƣ́ a 2 số tự nhiên N và M, + N dòng sau, mỗi dòng chƣ́a M số 0/1.
3 ≤ M ≤ 70 3 ≤ N ≤ 10000
- Output: Tệp văn bản CNMAX.OUT:
+ Dòng đầu tiên: Diện tích của hình chữ nhật tối đại chứa toàn kí tự 1.
+ Dòng thứ hai: Tọa độ cột và dòng của đỉnh trên - trái. + Dòng thứ ba: Toạ độ cột và dòng của đỉnh dƣới - phải.
Ví dụ: Với ma trận 7 x 8 chứa dữ liệu nhƣ hình 2.6 thì hình chữ nhật tối đại có diện tích là 10 ô vuông, có toạ độ đỉnh trên - trái là (Cô ̣t 2, dòng 4) và
28
đỉnh dƣới – phải là (cô ̣t 6, dòng 5)
CNMAX.INP CNMAX.OUT 7 8 0 0 0 0 1 0 0 1 0 1 1 0 1 1 0 1 0 1 1 0 0 1 0 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 1 0 10 2 4 6 5
Ý tưởng thuật toán [2], [3], [4], [8]
Để tìm đƣợc hình chữ nhật toàn 1 có diện tích lớn nhất, ta sẽ khởi tạo các mảng sau:
- Mảng H : H[i,j]: số ô 1 liên tiếp từ ô [i,j] trở lên = chiều rộng lớn nhất của HCN đáy dƣới qua ô [i,j].
- Mảng L : L[i,j]: số cột toàn 1 liên tiếp có chiều cao lớn hơn hoặc bằng H[i,j] tính từ cột j sang bên trái.
- Mảng R : R[i,j]: số cột toàn 1 liên tiếp có chiều cao lớn hơn hoặc bằng H[i,j] tính từ cột j sang bên phải.
Từ đó diện tích hình chữ nhật toàn 1 mà chiều rộng = H[i,j] và đáy dƣới ở hàng i là H*(L+R-1)
Vậy kết quả bài toán tìm diện tích hình chữ nhật lớn nhất toàn 1 là MAX(H*(L+R-1))
* Xét theo ví dụ trên:
1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1
1 1 1
- Tính mảng H : H[i,j] = 0 nếu A[i,j] = 0
Và = H[i-1,j]+1 nếu A[i,j]=1
0 0 0 0 1 0 0 1 0 1 1 0 2 1 0 2 0 2 2 0 0 2 0 3 0 3 3 1 1 3 0 4 1 4 4 2 2 4 1 0 0 0 5 0 0 0 0 0 0 0 6 0 0 1 1 0
- Tính mảng L : Duyê ̣t tất cả nhƣ̃ng phần tƣ̉ đƣ́ng trƣớc ô A [i,j] đang xét (tính theo chiều từ trái sang phải ), nếu thỏa mãn điều kiê ̣n liên tiếp = 1 và có độ cao >= H[i,j] thì L[i,j]=L[i,j-1]+1.
1 1 1 2 1 2 1 1 2 1 1 1 2 3 4 1 1 1 1 2 3 4 1 7 1 1 1 2
- Tính mảng R : Duyê ̣t tất cả nhƣ̃ng phần tƣ̉ đƣ́ng sau ô A [i,j] đang xét (tính theo chiều từ phải qua trái ), nếu thỏa mãn điều kiê ̣n liên tiếp =1 và có chiều cao >= H[i,j] thì R[i,j]=R[i,j+1]+1
30 1 1 2 1 1 1 1 2 1 1 1 2 1 3 2 1 1 7 2 1 3 2 1 1 1 1 2 1
Xét ô đƣơ ̣c đánh dấu, ta có: H = 2; L = 4; R = 2
Vậy diện tích hình chữ nhật chứa toàn 1 là: 2 x (4 +2 – 1) = 10 (đơn vị ô vuông)
Thuật toán
Algorithm CNMAX
Chức năng: Tìm diện tích hình chữ nhật tối đại chƣ́ a toàn kí tƣ̣ 1.
Input: Ma trận biểu diễn bằng một mảng hai chiều kích thƣớc N x M và
chỉ chứa các kí tự 0 và 1.
Output: Tìm hình chữ nhật chứa toàn kí tự 1 và có diện tích lớn nhất
(gọi là hình chữ nhật tối đại).
Method
1.Đo ̣c dƣ̃ liê ̣u tƣ̀ tê ̣p CNMAX.INP
1.1 Đọc 2 số nguyên ở dòng đầu của tệp vào 2 biến tƣơng ƣ́ng N , M
1.2 Đọc các số nguyên tƣơng ứng vào mảng A [i,j] for i:=1 to n do
begin
end;
2. Tính độ dài các cạnh :
2.1 Tính chiều cao hay chiều rộng của HCN thông qua mảng H for i:=1 to n do
for j:=1 to m do
if a[i,j]=0 then h[i,j]:=0 else h[i,j]:=h[i-1,j]+1;
2.2 Tính mảng L duyệt từ trái qua phải . for i:= 1 to n do
for j:=1 to m do
if a[i,j]=0 then l[i,j]:=0 else
begin d:=0;
for k:=1 to j do
if (a[i,k]=1) and (h[i,k]>=h[i,j]) then inc(d) else d:=0;
l[i,j]:=d; end;
2.2 Tính mảng R duyệt tƣ̀ phải qua trái. for i:=1 to n do
for j:=m downto 1 do if a[i,j]=0 then l[i,j]:=0 else
begin d:=0;
32
if (a[i,k]=1) and (h[i,k]>=h[i,j]) then inc(d) else d:=0;
r[i,j]:=d; end;
3.Tính các diện tích t ạo bởi các hình chữ nhật chƣ́a 1 và tìm diện tích lớn nhất chƣ́a toàn 1.
3.1 Khở i ta ̣o Smax:=0;
3.2 Tính diện tích các hì nh chƣ̃ nhâ ̣t; So sánh diê ̣n tích và gán giá tri ̣ diê ̣n tích lớn nhất tìm đƣợc vào biến S max; Xác định tọa độ các đỉnh trên – trái và dƣới – phải của HCN theo cột, dòng
for i:=1 to n do for j:=1 to m do begin S:=h[i,j]*(l[i,j]+r[i,j]-1); if S> smax then begin smax:=s; yt:=i+1-h[i,j]; xtr:=j+1-l[i,j]; yd:=i; xph:=xtr+(l[i,j]+r[i,j]-1)-1; end; end;
4. Đƣa ra kết quả gồm HCN tối đa ̣i chƣ́a toàn1, tọa độ đỉnh trên – trái và đỉnh dƣới – phải. (Ghi kết quả ra tệp CNMAX.OUT)
Tệp CNMAX.INP chứa n dòng, mỗi dòng chứa m kí tự. Khi xử lí để tính mảng H ta duyệt bằng hai vòng lặp for lồng nhau . Để tính mảng L và R ta duyệt bằng ba vòng lặp trong đó duyệt số phần tử m trên mỗi hàng là 2 lần. Viê ̣c tính giá trị của ba mảng H , L, R là đô ̣c lâ ̣p nên đô ̣ phƣ́c ta ̣p là: (n x m ) + ( n x m x m ) + ( n x m x m ). Khi n, m là rất lớn thì đô ̣ phƣ́c tạp là: n x m x m
Vậy độ phức tạp tính toán là O(n x m2 ).