压缩维度P1173+P1174+P1164
综述
这几天做了几道特别神奇的题目,让我感受到了算法的真正高效!这几道题的思路就是使劲压,从三维压到二维,从二维到一维,一维再优化,然后就可以将算法的复杂度下降很多很多。具体看下面的题:
一维累加和
题目描述:
给定N个数,求这N(1 <=N <= 100,000) 个数的某个连续子序列的累加和,保证这个连续子序列的累加和最大。
输入:
第一行:一个整数N。(1 <=N <= 100,000) 接下来N行,每行一个整数P_i(-1,000 <= P_i <= 1,000)。表示第i个数。
输出:
一个整数,表示子序列的最大连续累加和。
题解:
这道题首先来说……
单纯的进行一个个枚举然后加到一起最后排序是绝对不行的,因为复杂度是O(N*N*N)
,所以说,我们需要进行优化。
因为一个序列是要不停地加下去的,如果前面的序列是正的,那么加到后面肯定变大,而如果是负数,那么还不如不加。于是我们就可以计算累加和,如果前面的累加和是整数,继续加下去,并和maxx(用来记录最大值)比较。如果累加和是负数,清零,然后重新加。最后比较出来的maxx一定就是最大值!
然后O(N)
解决!
代码:
1 |
|
二维累加和(压缩要开始了)
题目描述:
给定一个正整数n( n<=500),然后输入一个N*N矩阵。求矩阵中最大加权矩形,即矩阵的每一个元素都有一权值,权值定义在整数集上。从中找一矩形,矩形大小无限制,是其中包含的所有元素的和最大 。矩阵的每个元素属于[-1100,1100]
输入:
第一行:n
接下来是n行n列的矩阵。
输出:
一个整数,表示最大子矩阵的和。
题解:
这道题书上有两种优化方法,一种是压缩维度,另一种就是预处理答案然后用公式,但是后者要慢很多慢很多。
具体方法:
第一种方法就是首先预处理出每一个位置 (x,y)
到 (1,1)
这个矩阵的累加和,用 a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1]+ans
(其中ans表示当前 a[i][j]
所在位置的初始值)这个公式的意思可以自己理解。然后我们就用O(N)的复杂度就解决了构建问题。
然后我们只需要再次使用一个公式,就可以求出 (x1,y1)
到 (x2,y2)
这个矩阵的累加和:num=a[x2][y2]-a[x1-1][y2-1]-a[x2][y1-1]+a[x1-1][y1-1]
这个公式就可以很好的求出啦;
再次的,我们使用一个四重循环,枚举每一个可能的矩形,然后计算出累加和,在和maxx比较赋值,最后留下来的答案就是最大的了;
BUT 看题目,数据范围是500 ,四次方呢……62 500 000 000 超时……
好不容易写出来的代码结果不对,妈卖批……
但是还有第二种更快的方法,就需要压缩了,压缩就是将一个求二维的压缩为求一维的方法,首先同样需要预处理,预处理出来这个矩阵中,纵向相加的值,比如在这个预处理的矩阵中 a[i][j]
就代表着,在第 j 列,前 i 行的所有累加和。
那么构建的方法也很简单,a[i][j]=a[i-1][j]+a[i][j]
; 然后我们就可以用 i 坐标相减的方法求出在 j 列,两个 i 坐标之间所有数的累加和,你可能想问,这样也不是有多高效啊,但是看P1173中优化的方法,就知道这个用优先队列找最大连续累加和的效率有多恐怖了。这样,我们只需要用一个二重循环确定这个矩阵的 x1 x2
然后利用一个一维数组 b[i]
存下在确定 x1 x2
的这种情况下,第 i 列的累加和,一个或者多个 b[i]
就构建出来了矩阵。然后由于我们已经压缩成了多个一维,所以参看P1173的优化方法。
O(N*N*N)
完美AC;
代码:
1 |
|
三维累加和
题目描述:
我们希望从一个mnh的三维矩阵中,找出一个三维子矩阵,这个子矩阵的权和最大其中对于全部的数据,1<=h<=32,1<=m,n<=50,保证h<=m,n;
输入:
首行三个数h,m,n(注意顺序),分别表示立方体的高,长,宽.
以下h部分,每部分是一个m*n的矩阵,第i部分第j行的第k个数表示立方体第i层,第j行第k列的那块1立方厘米的小正方体的权。
输出:
最大立方体累加和;
题解:
这道题,如果你天真的认为,数据范围不过50多,使劲搞,那真是超时就能超死你了。为什么呢? O(h*h*h*m*m*m*n*n*n)
大概也就相当于50的9次方吧 2*10^15
超时妥妥的。
但是,我们可以压缩,这道题的思路就是首先将三位压缩为一个一个二维,将二维分别压缩为一维,然后用优先队列的方法求出最大值。思路很简单,看到前两道题应该就能想出来,就是用一个二重循环枚举立方体的h的范围,然后将你所枚举的立方体进行累加和压缩,压缩成一个矩阵,压缩为矩阵之后就像上一道题的方法一样进行计算就好了。
但是刚开始有些绕,所以说建议将图画出来,模拟一下这个压缩的过程,压缩成矩阵后千万不要相信书上的方法,一定要将矩阵再次压缩成线性,不然还是超时,不要问我为什么,我是有亲身经历的。
不过压缩的时候方向也是有讲究的,题目中给出h要比n和m小,所以说我们可以换一个方向压缩,这样就可以优化成 O(h*h*n*m*m)
,这里的换个方向有可能就会在比赛中决定最后一两个数据的AC与否,所以说,能优化的一定要优化。
代码:
1 |
|