題目的意思很簡單,在一個矩陣裡面找它的子矩陣,使得子矩陣數值之和到達最大。其實就是最大子段和問題在二維空間上的推廣。先說一下一維的情況吧:設有數組a0,a1…an,找除其中連續的子段,使它們的和達到最大。假如對於子段:9 2 -16 2 temp[i]表示以ai結尾的子段中的最大子段和。在已知temp[i]的情況下,求temp
[i+1]的方法是:
如果temp[i]>0 temp [i+1]= temp[i]+ai(繼續在前一個子段上加上ai),否則temp[i+1]=ai(不加上前面的子段),也就是說 狀態轉移方程:
temp[i] = (temp[i-1]>0?temp[i-1]:0)+buf[i];
對於剛才的例子 temp: 9 11 -5 2,然後取temp[]中最大的就是一維序列的最大子段。求一維最大子段和的函數:
int getMax(int buf[100],int n)
{
int temp[101],max=n*(-127);
memset(temp,0,4*(n+1));
for(int i=1;i<=n;i++)
{
temp[i] = (temp[i-1]>0?temp[i-1]:0)+buf[i];
if(max<temp[i])
max=temp[i];
}
return max;
}
下面擴充到二維的情況:考察下面題目中的例子:
0 -2 -7 0
9 2 -6 2
-4 1 -4 7
-1 8 0 -2
我們分別用i j表示起始行和終止行,遍曆所有的可能:
for(i=1;i<=n;i++)
for(j=i;j<=n;j++) {}
我們考察其中一種情況 i=2 j=4,這樣就相當與選中了2 3 4三行,求那幾列的組合能獲得最大值,由於總是 2 3 4行,所以我們可以將這3行”捆綁”起來,變為求 4(9-4-1),11(8+2+1),-10(-6-4+0),7(7+2-2)的最大子段和,ok,問題成功轉化為一維的情況!
//acm pku 1050 To the Max by suqiang@neuq&jlu//更詳細的解題報告請訪問我的部落格:http://blog.csdn.net/china8848#include <stdio.h>#include <memory.h>//該函數求一維數組的最大子段和int getMax(int buf[100],int n){int temp[101],max=n*(-127);memset(temp,0,4*(n+1));for(int i=1;i<=n;i++){temp[i] = (temp[i-1]>0?temp[i-1]:0)+buf[i];if(max<temp[i])max=temp[i];}return max;}int main(void){int n,num[101][101],i,j,k,max,temp[101];scanf("%d",&n);for(i=1;i<=n;i++)for(j=1;j<=n;j++)scanf("%d",&num[i][j]);max = -127*n*n;for(i=1;i<=n;i++){memset(temp,0,4*(n+1));for(j=i;j<=n;j++){for(k=1;k<=n;k++){temp[k] += num[j][k];}//二維轉化為一維int this_max = getMax(temp,n);if(this_max>max)max = this_max;}}printf("%d/n",max);return 1;}