homework-01

参考书选择

选了电子版---[代码大全2英文版(完整清晰版)].chm

穷逼没钱买书好烦躁T.T

问题分析

一维的情况

最朴素最暴力的方法是枚举所有的sum[i,j],算出其值然后取最大。

时间复杂度为O(N^3),注意到sum[i,j]=sum[i,j-1]+a[i,j],所以不必每个sum[i,j]都重新算一遍,只需要通过前面的值来递推即可。时间复杂度降为O(N^2)

我们对所有的sum[i,j]来分类,用tail[j]表示所有的sum[i,j]的最大值,即tail[j]=max{sum[i,j]|1<=i<=j},表示所有由a[j]结尾的子串中的最大的和。

那么我们的目标转化为求最大的tail,不过这样分析起来似乎没有任何的优化。

不过我们发现,假设tail[j-1]已经求出了,那么tail[j]只有取两种情况:

  • 以tail[j-1]和a[j]组成新的子串
  • 放弃tail[j-1],重新由a[j]为一单独的新串。

因此我们得到如下状态转移方程:

tail[j]=max{tail[j-1]+a[j],a[j]}

求解问题只需从小到大遍历一遍O(N)的状态空间,每次转移需要O(1)时间复杂度,所以总共只有O(N)时间复杂度。

二维的情况

在有了一维度的解答之后,我们很容易想到通过枚举上下界来把二维的问题转化为一维,需要枚举C(N,2)+N种上下界,每一种需要O(M)时间复杂度来计算,因此总共需要O(N^2*M)的时间复杂度

编程实现

一维的情况

 1 #include<stdio.h>
 2 #define MAXN 100000
 3 #define MINV (-(1<< 31 -1))
 4 int maxsum(int p[],int size)
 5 {
 6     int i,sum,ans;
 7     ans=MINV;
 8     sum=0;
 9     for (i=0;i<size;i++)
10     {
11         if (sum<0)
12             sum=0;
13         sum+=p[i];
14         if (sum>ans)
15             ans=sum    ;    
16     }
17     return ans;
18 }
19 int main()
20 {
21     int i,n,p[MAXN];
22     freopen("input1.txt","r",stdin);
23     freopen("output1.txt","w",stdout);
24     scanf("%d,",&n);
25     for(i=0;i<n;i++)
26                     scanf("%d,",&p[i]);
27     printf("%d\n",maxsum(p,n));
28     return 0;
29 }
View Code

二维的情况

 1 #include<stdio.h>
 2 #define MAXN 1000
 3 #define MAXM 1000
 4 #define MINV (-(1<< 31 -1))
 5 int n,m,a[MAXN][MAXM];
 6 int maxsum(int N,int M)
 7 {
 8     int i,j,k,sum,ans;
 9     int p[M];
10     for (i=0;i<M;i++) p[i]=0;
11     ans=MINV;
12     sum=0;
13     for (i=0;i<N;i++)
14         {
15         for(j=i;j<N;j++)
16             {
17             sum=0;
18             for (k=0;k<M;k++)
19                 {
20                 p[k]+=a[j][k];
21                 if (sum<0)
22                     sum=0;
23                 sum+=p[k];
24                 if (sum>ans)
25                     ans=sum;
26                 }
27             }
28         for (k=0;k<M;k++)p[k]=0;
29         }
30     return ans;
31 }
32 int main()
33 {
34     int i,j;
35     freopen("input2.txt","r",stdin);
36     freopen("output2.txt","w",stdout);
37     scanf("%d,",&n);
38     scanf("%d,",&m);
39     for(i=0;i<n;i++)
40     for(j=0;j<m;j++)
41                     {
42                     scanf("%d,",&a[i][j]);
43                     //printf("%d ",a[i][j]);
44                     }
45     printf("%d\n",maxsum(n,m));
46     return 0;
47 }
View Code

测试结果

input1.txt

6,
5,6,-3,8,-9,2

output1.txt

  16

input2.txt

3,
6,
5,6,-3,8,-9,2
1,-12,20,0,-3,-5
-9,-7,-3,6,7,-1

output2.txt

  28

posted @ 2013-09-19 19:52  Forwil  阅读(197)  评论(1编辑  收藏  举报