noi openjudge 1768:最大子矩陣

連接:http://noi.openjudge.cn/ch0406/1768/spa

 

描述
已知矩陣的大小定義爲矩陣中全部元素的和。給定一個矩陣,你的任務是找到最大的非空(大小至少是1 * 1)子矩陣。3d

好比,以下4 * 4的矩陣code

0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2blog

的最大子矩陣是it

9 2
-4 1
-1 8io

這個子矩陣的大小是15。
輸入
輸入是一個N * N的矩陣。輸入的第一行給出N (0 < N <= 100)。再後面的若干行中,依次(首先從左到右給出第一行的N個整數,再從左到右給出第二行的N個整數……)給出矩陣中的N2個整數,整數之間由空白字符分隔(空格或者空行)。已知矩陣中整數的範圍都在[-127, 127]。
輸出
輸出最大子矩陣的大小。
樣例輸入
4
0 -2 -7 0 9 2 -6 2
-4 1 -4 1 -1class

8 0 -2
樣例輸出
15循環

 

芒果君:第一次看到這道題,仍是在貪內心,就特別懵逼,後來dalao教我用矩陣前綴和來寫,畫個圖的話就很容易理解啦~im

(a:元素,sum:從a(1,1)到a(i,j)全部值的和,就是前綴和。)img

邊讀入邊求前綴和(sum),用這個公式來求:①+②+③-④ 得出sum(5,3)=a(5,3)+sum(4,2)+sum(5,2)-sum(4,2);

好像有點遞推思想呢?

而後四重循環暴力枚舉全部子矩陣,找到最大值!

 

 

公式:①-②-③+④,枚舉出(2,2)到(5,3)的矩陣大小t=sum(5,3)-sum(5,1)-sum(1,3)+sum(1,1),更新最大值。代碼以下——

 

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 int ju[110][110],sum[110][110],n,i,j,k,l,ans;
 5 int main()
 6 {
 7     scanf("%d",&n);
 8     for(i=1;i<=n;++i)
 9         for(j=1;j<=n;++j){
10             scanf("%d",&ju[i][j]);
11             sum[i][j]=ju[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
12         }
13     for(i=1;i<=n;++i)
14         for(j=1;j<=n;++j)
15             for(k=1;k<=i;++k)
16                 for(l=1;l<=j;++l)
17                     ans=max(ans,sum[i][j]+sum[k-1][l-1]-sum[i][l-1]-sum[k-1][j]);
18     printf("%d",ans);
19     return 0;
20 }

 

 

而後呢,這道題用DP作就是醬紫的(參考最大子序列和)~讀入的時候求每一列的前綴和,再用三重循環把它處理成子矩陣(i,j限制行的範圍,k是列)。抽象的看,是由線到面的轉化。

 

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 int ju[110][110],f[110],n,i,j,k,ans;
 5 int main()
 6 {
 7     scanf("%d",&n);
 8     for(i=1;i<=n;++i)
 9         for(j=1;j<=n;++j){
10             scanf("%d",&ju[i][j]);
11             ju[i][j]+=ju[i-1][j];
12         }
13     for(i=1;i<=n;++i)
14         for(j=1;j<i;++j){
15             for(k=1;k<=n;++k)
16                 f[k]=ju[i][k]-ju[j][k];        
17             for(k=1;k<=n;++k){
18                 f[k]=max(f[k],f[k-1]+f[k]);
19                 ans=max(ans,f[k]);
20             }
21         }
22     printf("%d",ans);
23     return 0;
24 }

 

 

各位dalao看懂了嗎?沒看懂也不關個人事~

(最後不負責任的博主在一片罵聲中點下了保存修改)

相關文章
相關標籤/搜索