【HDU】1081 To The Max

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1081

初步看到这种题目的时候第一思路肯定是暴力,O(n^4)  …… = = …… 显然不行

然后,就得想办法优化,想了半天,没辙,于是放弃了。

                                                                            ———去年的时候的真实想法

今年再做的时候,emm… 不就是DP么?(因为是在DP专题练习的时候twinkle给拉出来再做的)   肯定有办法的吧,再想想…

慢慢的,思路涌出来了,整个过程回放:

求所有子矩阵的最大的和,他会和DP扯上什么关系呢?

后来不知yy了多久,突然想到了一道dp基础题:http://acm.hdu.edu.cn/showproblem.php?pid=1231 

这两道题目的共同点在于都是求最大连续子段的和……

顺着这个想法下去,很快又想到去年学习某个算法(名字在我脑中已经置零了…… = = )时,将一个多元、多维问题转化为一元……

接着我的第一个idea就诞生了!(不过,这个方法和网上大神们的方法相比就逊色多了……)

如图:(额… 我的画图水平就真的只有这么点儿了,不要见怪…)   PS: 前提假设矩阵下标是从0~n-1

首先建立一个3维数组row[k][i][j],k:代表压缩的长度 (1<=k<=n),i代表所在的起始层数 (0<=i<=n-1),j代表列数 (0<=j<=n-1)。 那么row[k][i][j] = ∑(k=i~k=n-i)∑(i=0~n-1)∑(j=0~n-1) matrix[i][j]。 

创建好row[][][]数组之后,只需要在k、i这两维上进行求 最大连续子序列 即可。

我个人感觉这种做法就类似于将一个二维的矩阵压缩成一维,虽然这里我用的是三维数组来存储,但在逻辑上(这个说法感觉有点猥琐…)还是降到一维了……

很挫的代码如下:

Build row
memset(row,0,sizeof(row));
        for(k=0; k<n; ++k)
            for(i=k; i<n; ++i)
                   for(j=0; j<n; ++j){
                                if(i==k)  row[k][i][j] = mat[k][j];
                                else    row[k][i][j] = mat[i][j]+row[k][i-1][j];
                        }
Get maxnumber
 1              tmax=0;
 2              max = -1*MAXN*MAXN*MAXN;
 3 
 4              for(k=0; k<n; ++k){
 5                  tmax = 0;
 6                      for(i=k; i<n; ++i){ tmax = 0;
 7                           for(j=0; j<n; ++j){
 8                             tmax+=row[k][i][j];
 9                             if(tmax<=0) tmax = 0;
10                             if(max<tmax)    max = tmax;
11                    }
12              }
13              }
14              cout<<max<<endl;

 

但是写完后提交的结果是TLE……

我顿时杵在电脑前了,碎了一地的心那…… (后来回过头检查代码的时候,发现是 while(~scanf("%d",&n)) 的时候~没有加,又伤了一地的心)

于是百度了这道题目的做法,这才有缘认识到大神们的做法。

tmax=0;
max = -1*MAXN*MAXN*MAXN; 
for(k=0; k<n; ++k){
      memset(row,0,sizeof(row));
      for(i=k; i<n; ++i){
            for(j=0; j<n; ++j){
                 row[j]+=mat[i][j];
            }
            tmax=GetMax();
            if(max<tmax)  max= tmax;
        }
 }
 cout<<max<<endl;

其实两种做法的本质还是一样的,只是就代码的精简、美观等角度看来,还是大神们的更好啊~~

这次也学习到啦!

posted on 2012-07-21 16:32  Yuna_  阅读(81)  评论(0)    收藏  举报