链接:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=113&page=show_problem&problem=44
原题:
A problem that is simple to solve in one dimension is often much more difficult to solve in more than one dimension. Consider satisfying a boolean expression in conjunctive normal form in which each conjunct consists of exactly 3 disjuncts. This problem (3-SAT) is NP-complete. The problem 2-SAT is solved quite efficiently, however. In contrast, some problems belong to the same complexity class regardless of the dimensionality of the problem.
Given a 2-dimensional array of positive and negative integers, find the sub-rectangle with the largest sum. The sum of a rectangle is the sum of all the elements in that rectangle. In this problem the sub-rectangle with the largest sum is referred to as the maximal sub-rectangle. A sub-rectangle is any contiguous sub-array of size or greater located within the whole array. As an example, the maximal sub-rectangle of the array:
is in the lower-left-hand corner:
and has the sum of 15.
The input consists of an array of integers. The input begins with a single positive integer N on a line by itself indicating the size of the square two dimensional array. This is followed by integers separated by white-space (newlines and spaces). These integers make up the array in row-major order (i.e., all numbers on the first row, left-to-right, then all numbers on the second row, left-to-right, etc.). N may be as large as 100. The numbers in the array will be in the range [-127, 127].
The output is the sum of the maximal sub-rectangle.
4 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2
15
题目大意:
给一个N*N大小的矩阵,每个格子上有一个数字。 求这个矩阵中的子矩阵上面数字之和最小的数字是多少。
分析与总结:
经典的一道题。 也可以说是“最大连续和"那题(UVa 507 - Jill Rides Again) O(n)算法的升级版本。
这题的关键在于转化, 就是把矩阵上面的那些数转换成”最大连续和“。
看下图(画得实在有点对不起观众 = =)
把那些格子看成数字, 上面有红色斜线阴影的代表其中一个高度为2的子矩阵, 我们可以把这两层看做是一层, 上下层数字之和代表一个新的数字, 就可以用“最大连续和”的O(n)方法求出斜线阴影部分最大的一个2*x的矩阵之和。
要求整个大矩阵的最大子矩阵数字和, 就需要枚举所层数的情况,需要用两层for循环。 加上里面那个O(n)的线性时间扫描,最终复杂度是O(n^3).
代码:
/*
* UVa: 108 - Maximum Sum
* Time: 0.012s
* Author: D_Double
*
*/
#include
#include
#include
#define MAXN 102
using namespace std;
int arr[MAXN][MAXN],sum[MAXN][MAXN];
int mx,sm;
int main()
{
int T,m,n,x,y;
int i,j;
while(~scanf("%d",&n)){
memset(sum,0,sizeof(sum));
memset(arr,0,sizeof(arr));
for(i=1; i<=n; ++i){
for(j=1; j<=n; ++j) {
scanf("%d",&arr[i][j]);
// sum[i][j] 表示对角顶点为(1,1),(i,j)这个矩阵里面所有原数之和
sum[i][j] = sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+arr[i][j];
}
}
int maxSum=-2147483645;
for(int i=1; i<=n; ++i){
for(int j=0; jmaxSum) maxSum=t;
if(sum[i][k]-sum[j][k] < min)
min=sum[i][k]-sum[j][k];
}
}
}
printf("%d\n", maxSum);
}
return 0;
}
附:这题的又一次升级版 UVa 10827 - Maximum sum on a torus
—— 生命的意义,在于赋予它意义。