這一題是給一個二維陣列,要找出有最大和的子陣列,傳回和的值。原本想不出更好的方法,只好用brute force搜尋所有子陣列 ,但預料之內的Time Limit Exceed(UVa好厲害啊)。查了資料,才知道解決之道在於 Kadane’s Algorithm。
Kadane’s Algorithm可以O(n)找到一維陣列的最大和子序列,Algorithmist上的pseudo code如下:
Kadane's Algorithm(arr[1..n]) begin (max, a, b) := (-INFINITY, 0, 0) curr := 0 aa := 1 for bb := 1 to n do curr := curr + arr[bb] if curr > max then (max, a, b) := (curr, aa, bb) endif if curr < 0 then curr := 0 aa := bb + 1 endif endfor return (max, a, b) end
即是從陣列頭開始,不斷累加陣列元素值,同時不斷更新最大值,一旦累加和<0,就把累加變數歸零。因為一旦是負數,下一個元素值不管是正數或負數,都只會越加越小,所以不可能會是maximum了。如此,只需要讀過一次陣列就可以找到最大和子序列,真是神奇啊!
CODE
#include <stdio.h> #define MAX 100 int main(){ int i, j, k; int n, t[MAX][MAX], sum, max; scanf("%d", &n); for(i=0; i<n; i++) for(j=0; j<n; j++) scanf("%d", &t[i][j]); /*calculate vertical sum*/ for(i=0; i<n; i++){ for(j=1; j<n; j++){ t[j][i] += t[j-1][i]; }/*j: row*/ }/*i: column*/ max = t[0][0]; /*find max sum*/ for(i=0; i<n; i++){ for(j=i; j<n; j++){ sum = 0; for(k=0; k<n; k++){ if( i==j || i==0 ) sum += t[j][k]; else sum += ( t[j][k] - t[i-1][k] ); if( sum > max ) max = sum; else if( sum < 0 ) sum = 0; } }/*j: ending row*/ }/*i: starting row*/ printf("%d\n", max); exit(0); }
No comments:
Post a Comment