最大子阵和

题目链接: http://exercise.acmcoder.com/online/online_judge_ques?ques_id=3352&konwledgeId=40

解题思路: 首先,考虑一维的情况。a1,a2,a3,....an的最大子序列和。我们维护一个(最大前缀和),当这个前缀和小于0的时候,就替换为当前值,那么最大值一定在这些前缀和中。

然后对于二维的情况,我们枚举可能的起始列标,这样就是一维的最大子序列和的问题了。例如,当我们选定第一列和第三列后,把每一行第一列到第三列的数加在一起,那么就是一个一维的问题了。对于给定区间的和,我们可以通过前缀和O(1)计算,sum[i,j]=sum[0,j]-sum[0,i-1]。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 const int MAXN=100005;
 6 const LL MON7 = 1e9+7;
 7 int a[105][105];
 8 int sum[105][105];
 9 int n,m;
10 
11 void solve()
12 {
13     int ans=-2000;
14     for (int p=1;p<=m;++p)
15     {
16         for (int q=p;q<=m;q++)
17         {
18             int tmp=-2000;
19             for (int i=1;i<=n;++i)
20             {
21                 if (tmp<0) tmp=sum[i][q]-sum[i][p-1];
22                 else tmp+=sum[i][q]-sum[i][p-1];
23                 ans=max(ans,tmp);
24             }
25         }
26     }
27     printf("%d\n",ans);
28 }
29 
30 int main()
31 {
32 #ifndef ONLINE_JUDGE
33     freopen("test.txt","r",stdin);
34 #endif // ONLINE_JUDGE
35     int Case;
36     scanf("%d",&Case);
37     while (Case--)
38     {
39         scanf("%d%d",&n,&m);
40         memset(sum,0,sizeof(sum));
41         for (int i=1;i<=n;++i)
42         {
43             for (int j=1;j<=m;++j)
44             {
45                 scanf("%d",&a[i][j]);
46                 sum[i][j]=sum[i][j-1] + a[i][j];
47             }
48         }
49         solve();
50     }
51     return 0;
52 }

 

posted @ 2018-04-26 21:20  只会一点暴力  阅读(147)  评论(0编辑  收藏  举报