題目描述
一日,小A走在路上時看到路邊擺著一面大鏡子。 他對著這面鏡子注視了半天,突然發現自己穿越到了另一個世界!這個世界很奇怪:他所在的地方可視為一個n行m列的矩陣,每一個位置上都有一一個非負整數或者-1。這時,他的耳邊響起了一一個很空靈的聲音:”如果您想要回到原來的世界, 你需要解決下面的問題:你需要在整個矩陣上選擇一 一個正方形區域,使得該區域不包含任何負數,并且該區域內的數字之和最大。“然而這個問題對于小A來說還是太難了,所以他請了你來幫忙解決這個問題。
輸入描述
第一行一個正整數T,表示一共有T組數據。
對于每組數據,第一行兩個正整數n,m,含義見題面;
接下來一一個n行m列的整數矩陣j.
1 ≤ n,m ≤ 500,1 ≤ T ≤ 5.aij∈(-1,[0,100])
輸出描述
對于每組數據,輸出一行個正整數,表示滿足條件的最大值。如果該矩陣全為-1,則輸出0.
樣例輸入
1
4 4
12 0 0 6
0 0 -1 4
-1 8 1 1
4 -1 5 -1
樣例輸出
12
解法
public class Main{
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream("data.txt")
));
int T = Integer.parseInt(br.readLine().trim());
while (T-- != 0) {
String[] inputs = br.readLine().trim().split(" ");
int n = Integer.parseInt(inputs[0]);
int m = Integer.parseInt(inputs[1]);
int[][] nums = new int[n][m];
for (int i = 0; i < n; i++) {
inputs = br.readLine().trim().split(" ");
for (int j = 0; j < m; j++) {
nums[i][j] = Integer.parseInt(inputs[j]);
}
}
System.out.println(process(n, m, nums));
}
}
private static int process(int n, int m, int[][] nums) {
if (n == 0 || m == 0) return 0;
int res = 0;
int[][] dp = new int[n + 1][m + 1];
int[][] sums = new int[n+1][m+1];
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
sums[i][j] = nums[i-1][j-1] + sums[i-1][j] + sums[i][j-1] - sums[i-1][j-1];
if (nums[i - 1][j - 1] != -1) {
// 最短的邊
int minEdge = Math.min(dp[i][j - 1], Math.min(dp[i - 1][j - 1], dp[i - 1][j])) ;
dp[i][j] = 1 + minEdge; // 加上自己本身
int len = dp[i][j];
int top = i - len;
int left = j - len;
int sum = sums[i][j] - sums[i][left] - sums[top][j] + sums[left][top];
res = Math.max(res, sum);
}
}
}
return res;
}
}