8
Bài toán ma trn con có tng ln nhấ – [email protected] - 1 - Bài toán con ổ ớ ấ (Maximum sub rectangle) 19/03/2010) There are wavelengths that people cannot see, there are sounds that people cannot hear, and maybe computers have thoughts that people cannot thinkDr. Richard W. Hamming (1915-1998) Qui hoạc ộng c c . 1. ậ ổ ớ ấ c c c c ộ c c cc cc nguyên thuc khong [-127, 127] (1 < N, M 100) ộ c (gm các phn t lin k ca ma tr u) c cc c . Ma tr u là Thì ma trn con có tng ln Tng các phn t ca ma trn kết qu 15 T ờng hp có nhiu kết quthì chcn ly kết quu tiên. Thut toán thnht cho thu ơ ản: chúng ta xét hết tt ccác ma trn con có th có ca ma tr u, tính t ơ ứng ca chúng và tìm ra tng ln nht. Các bạ ộc gicó th ddàng nhn thy rng thut toán này s c ộ phc tp O(N, M) = N 3 x M 3 . Vi giá trN = M = 100phc tp thut toán s O(N, M) = 10 2*3*2 = 10 12 , và tt nhiên con s này là không thc tế i vi các máy PC hin nay. T cc ạ ạc ộ ả ế tìm ma trn con có tng ln nht ộ ức ạ ờ ả 2. Thut toán 1: quy hoạ động da trên việ í ước tng ca các ma trn con xut phát tphn tvtrí (0, 0). Thut toán thnh gii quyết bài toán da trên vic xây dng mt mả [][] c ị ĩ , 0 i*j=0 [][ ] [ ][ ] r ic j dp i j dr c (1) â ảng d[][] là mng các phn t ca ma tr u (chs 0).

Maximum Sum

Embed Size (px)

Citation preview

Page 1: Maximum Sum

Bài toán ma trận con có tổng lớn nhấ –

[email protected] - 1 -

Bài toán ậ con ổ ớ ấ

(Maximum sub rectangle)

19/03/2010)

“There are wavelengths that people cannot see, there are sounds that people cannot hear, and maybe computers have thoughts that people cannot think” Dr. Richard W. Hamming (1915-1998)

Qui hoạc ộng c c .

1. ậ ổ ớ ấ

c c c c ộ c

c c c c c nguyên thuộc khoảng [-127, 127] (1 < N, M ≤ 100)

ộ c (gồm các ph n t li n k c a ma tr u) c c c

c .

Ma tr u là

Thì ma tr n con có t ng l n

T ng các ph n t c a ma tr n kết quả 15 T ờng h p có nhi u kết quả thì

chỉ c n l y kết quả u tiên.

Thu t toán thứ nh t cho thu ơ ản: chúng ta xét hết t t cả các ma tr n con

có th có c a ma tr u, tính t ơ ứng c a chúng và tìm ra t ng l n nh t. Các

bạ ộc giả có th dễ dàng nh n th y rằng thu t toán này s c ộ phức tạp O(N, M) = N3 x

M3. V i giá trị N = M = 100 ộ phức tạp thu t toán s là O(N, M) = 102*3*2 = 1012, và t t

nhiên con s này là không thực tế i v i các máy PC hiện nay.

T c c ạ ạc ộ ả ế

tìm ma tr n con có t ng l n nh t ộ ức ạ ờ ả

2. Thuật toán 1: quy hoạ động dựa trên việ í ước tổng của các ma trận

con xuất phát từ phần tử ở vị trí (0, 0).

Thu t toán thứ nh giải quyết bài toán dựa trên việc xây dựng một mả [][] c

ị ĩ

,

0 i*j=0

[ ][ ] [ ][ ]r i c j

dp i j d r c

(1)

Ở â ảng d[][] là mảng các ph n t c a ma tr u (chỉ s ừ 0).

Page 2: Maximum Sum

Bài toán ma trận con có tổng lớn nhấ –

[email protected] - 2 -

Việc tính các giá trị c a mả [][] c thực hiện theo công thức truy hồi sau:

dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1]+d[i-1][j-1]; (2)

V i mả [][] c c này chúng ta có th c t ng các ph n t c a một

ma tr n con nằm từ cột j t i cột j+col và từ hàng i t i hàng i + row theo công thức sau:

sum = dp[i+row+1][j+col+1] -dp[i+row+1][j]-dp[i][j+col+1] +dp[i][j]; (3)

Các bạn có th xem hình minh họ hi õ ơ c ức trên.

0, 0

n, m

i, jcol

row

i+row, j+col

K c ú c ỉ c n 4 vòng lặp lồ duyệt qua t t cả các ma tr n con có th

có c a ma tr u, tính t ng các ph n t trong ma tr n con theo công thức (3) ở trên

và tìm ra t ng l n nh t.

C th thu c c ặ

int findMax2(int n, int m) // O(N^2M^2)

{

int maxSum = d[0][0];

int sum;

int i, j;

int col, row;

// initial dp array

for(i=1;i<=n;i++)

for(j=1;j<=m;j++)

dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1]+d[i-1][j-1];

cout << endl;

Page 3: Maximum Sum

Bài toán ma trận con có tổng lớn nhấ –

[email protected] - 3 -

for(i=0;i<n;i++)

for(j=0;j<m;j++)

for(row=0;i+row<n;row++)

for(col=0;j+col<m;col++)

{

// watch out here in index of dp array

sum = dp[i+row+1][j+col+1]+dp[i][j]-dp[i+row+1][j]-dp[i][j+col+1];

if(sum>maxSum)

maxSum = sum;

}

return maxSum;

}

Thu c ộ phức tạp O(N, M) = N2 x M2 ờng h = = 100 ộ

phức tạp c th là 108, con s này là có th ch p nh c (chạ ò c ến 0,5

giây).

3. Bài toán dãy con có tổng lớn nhất và thuật toán Kadane cho mảng 1 chiều

T c khi xem xét thu t toán thứ 2 cho bài toán chúng ta s xem xét bài toán tìm dãy

con (gồm các ph n t liên tiếp nhau) có t ng l n nh t trong một mảng một chi u và thu t

toán Kadane (Joseph B. Kadane - http://lib.stat.cmu.edu/~kadane/) cho bài toán này.

Thu t toán Kadane s d ng kỹ thu t quy hoạc ộ ơ ả giải quyết bài toán

theo công thức truy hồi sau:

for x in a[0..n-1]

temp_max = max(0, temp_max) + x;

max_sum = max(max_sum, temp_max);

giá trị 0 c ờng h p mảng không có ph n t nào (t ng các ph n t ứ c x

nhỏ ơ 0) c lại giá trị l n nh t c a mảng tính t i ph n t x s là giá trị l n nh ạt

c v i mảng gồm các ph n t c x cộng thêm v i x.

ặt c th cho thu

int max_subarray(int a[], int n)

{

// end và start là hai biến toàn c c ghi lại vị trí bắ u và kết thúc c a nghiệm

// thu t toán Kadane

int temp_max = 0;

int max_sum = 0;

int i, temp_start = 0;

for(i=0;i<n;i++)

Page 4: Maximum Sum

Bài toán ma trận con có tổng lớn nhấ –

[email protected] - 4 -

{

temp_max += a[i];

if(temp_max<0)

{

temp_max = 0;

temp_start = i+1;

}

if(temp_max>max_sum)

{

start = temp_start;

end = i;

max_sum = temp_max;

}

}

return max_sum;

}

Thu c ộ phức tạp O(N) = N.

4. Thuật toán Kadane cho bài toán tìm ma trận con có tổng lớn nhất.

Bây giờ chúng ta s áp d ng thu t toán Kadane cho bài toán tìm ma tr n con (hai một

mảng hai chi u) có t ng l n nh t. Ta xem mỗi ma tr n con a[0..n-1, col..(col+span)] gồm các

ph n t a[][] chạy từ hàng 0 (bắ u) t i hàng n-1 (kết thúc) và từ cột col t i cột col+span

c a ma tr u là một mảng một chi u v i các ph n t là t ng c a các ph n t trên

một hàng c a ma tr c ức là:

owSum[ ow] [ ow][ ]col j col span

r r a r j

K ng thu t toán Kadane cho mảng một chi u rowSum[] ta s c mảng

con gồm các ph n t liên tiếp có t ng l n nh t c a mả c n con có

t ng l n nh t c a ma tr n con a[0..n-1][col..(col+span)], và cho biến col chạy từ 0 t i m-1 ta

s có kết quả c a bài toán là giá trị l n nh c qua mỗi l n lặp.

Các bạn có th xem qua hình minh họa sau:

Page 5: Maximum Sum

Bài toán ma trận con có tổng lớn nhấ –

[email protected] - 5 -

0, 0

n, m

Xé cộ c span

ộ c + span

sumRow[0]

sumRow[1]

sumRow[n-1]

ặt c th c a thu t toán (bằng ngôn ngữ C++) là:

#include <iostream>

#include <fstream>

#include <ctime>

using namespace std;

const int MAXN = 5000;

const int MAXVAL = 30;

int d[MAXN][MAXN];

int dp[MAXN][MAXN];

int rowSum[MAXN]; // sum of row

void genTest(int n, int m);

// gen data for array d[0..n-1][0..m-1]

void printArray(int i, int j, int n, int m);

int topLeftX, topLeftY, botRightX, botRightY; // location of result

int findMax(int n, int m); // O(NM^2)

int n, m;

int main()

{

Page 6: Maximum Sum

Bài toán ma trận con có tổng lớn nhấ –

[email protected] - 6 -

clock_t st, et;

n = m = 100;

genTest(n, m);

//printArray(0, 0, n, m);

cout << endl;

st = clock();

cout << findMax(n, m) << endl;

et = clock();

cout << "Thoi gian:" << (et-st)/CLK_TCK;

system("pause");

return 0;

}

int findMax(int n, int m)

{

int col, row, span;

int maxSum = d[0][0];

int sum;

int temp_start;

for(col=0;col<m;col++)

{

// fix column col

// init rowSum array

memset(rowSum,0, n*sizeof(int));

for(span=0;span+col<m;span++)

{

sum = 0;

// colum: span+col

// recalculate rowSum array

for(row=0;row<n;row++)

rowSum[row] += d[row][col+span];

temp_start = 0; // row 0

for(row=0;row<n;row++)

{

sum += rowSum[row];

Page 7: Maximum Sum

Bài toán ma trận con có tổng lớn nhấ –

[email protected] - 7 -

if(sum<0)

{

temp_start = row+1;

sum = 0;

}

if(sum>maxSum)

{

maxSum = sum;

topLeftX = temp_start;

topLeftY = col;

botRightX = row+1;

botRightY = col+span+1;

}

}

}

}

return maxSum;

}

void genTest(int n, int m)

{

srand((int)time(NULL));

int i, j;

for(i=0;i<n;++i)

for(j=0;j<m;++j)

d[i][j] = (rand()%MAXVAL) - MAXVAL/2;

}

void printArray(int i, int j, int n, int m)

{

int i1, j1;

for(i1=i;i1<n;++i1)

{

for(j1=j;j1<m;++j1)

cout << d[i1][j1] << " ";

cout << endl;

Page 8: Maximum Sum

Bài toán ma trận con có tổng lớn nhấ –

[email protected] - 8 -

}

}

Mặc ù ết sức th n trọng và xem xét kỹ c c g bài viết, tuy

v y vẫn có th không tránh khỏi các sai sót, r t mong nh c sự ý ến c a

các bạ ộc giả. Mọi góp ý, thắc mắc xin g i v ịa chỉ email: [email protected].

Hải Phòng, ngày 14, tháng 03, ăm 2010

Nguyễn Hữu Tuân