1. 程式人生 > >子矩陣最大累加和(動態規劃)

子矩陣最大累加和(動態規劃)

描述 給定一個由整陣列成二維矩陣(r*c),現在需要找出它的一個子矩陣,使得這個子矩陣內的所有元素之和最
大,並把這個子矩陣稱為最大子矩陣。例子: 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2 其最大子矩陣
為: 9 2 -4 1 -1 8 其元素總和為15。 輸入 第一行輸入一個整數n(0<n<=100),表示有n組測試資料; 每組
測試資料: 第一行有兩個的整數r,c(0<r,c<=100),r、c分別代表矩陣的行和列; 隨後有r行,每行有c個整
數; 輸出 輸出矩陣的最大子矩陣的元素之和。
樣例輸入 
1 
4 4 
0 -2 -7 0 
9  2 -6 2 
-4 1 -4 1 
-1 8 0 -2 
樣例輸出 
15

第一,如何更簡單地計算出一個子矩陣的和?

先考慮子問題行數固定的矩陣(i=2,j=4)k=1~4裡的矩陣哪個累加和最大,把所有的列相加得到一個一維資料,求一維資料的最大累加和。在資料錄入的時候,就應該是num[i]+=num[i-1],這樣,要計算從j到i的資料之和,直接num[i]-num[j-1]就能直接得出了

第二,如何求陣列的最大累加和

如果某段資料累加和出現負數那麼這段資料一定不是最大累加和資料段的一部分,從第一個數開始累加如果tempmax出現負數,tempmax置為0,重新開始累加。max記錄最大的tempmax

第三,如何遍歷出所有可能的子矩陣?

這裡可以使用三個變數i,j,k來遍歷。如果一個矩陣大小是M*N的,那麼可以使i從0到M,再使j從每一個i到M,這樣就把行方向給遍歷完了。再考慮列方向,直接在每一種i,j組合下,進行0到N的遍歷,那麼這樣就等於是把所有子矩陣的情形給遍歷完了。

程式碼如下:  


public class 最大子矩陣 {

	private static int num[][] = new int[101][101];
	private static int n;
	private static Scanner input = new Scanner(System.in);

	public static void main(String[] args) {
		getMax();
	}
	public static int getMax() {

		n = input.nextInt();
		n = n - 1;
		while (n  >= 0) {
			int r, c;
			r = input.nextInt();
			c = input.nextInt();
			int i, j, k;
			initArr(r,c,num);
			for (i = 1; i <= r; i++)
				for (j = 1; j <= c; j++) {
					num[i][j] = input.nextInt();
					num[i][j] += num[i - 1][j];
				}
			int temp = 0;
			int max = num[1][1];
			int tempmax;
			for (i = 1; i <= r; i++) {
				for (j = i; j <= r; j++) {
					tempmax = 0;
					for (k = 1; k <= c; k++) {
						temp = num[j][k] - num[i - 1][k];
						tempmax = (tempmax >= 0 ? tempmax : 0) + temp;
						max = tempmax > max ? tempmax : max;
					}
				}
			}
			System.out.println(max);
		}
		return 0;
	}

	public static  void initArr(int r, int c, int[][] a) {
		for (int i = 0; i < r; i++) {
			for (int j = 0; j < c; j++) {
				a[i][j] = 0;
			}
		}
	}

}