zoukankan      html  css  js  c++  java
  • 【降维解法:最大字段和->最大子矩阵和->最终版最大子长方体和】【UVA10755】Garbage Heap

    突然感觉刷完这一套专题后 码力有了质的飞跃,fighting 努力会有结果!


    最大字段和是一个很经典的问题 O(n)算法


    而对于最大子矩阵和

    可以思考一个这样的想法

    枚举上下边界i,j把i到j这一段的矩阵上下挤压成一个序列

    对于i到j的最大子矩阵和问题=求这个序列的最大字段和

    所以 复杂度为O(n^3)


    而对于最大子长方体和 

    依旧 先枚举上下边界 使问题变成最大子矩阵和

    复杂度 O(n^5)


    这种降维解题的思维方式 十分不错


    具体看下面这个题

    废料堆(Garbage Heap, UVa 10755)


    有个长方体形状的废料堆,由A×B×C个废料块组成,每个废料块都有一个价值,可正可负。现在要在这个长方体上选择一个子长方体,使组成这个子长方体的废料块的价值之和最大。

    【输入格式】

    输入的第一行为数据组数TT≤15)。每组数据的第一行为3个整数A, B,C(1≤A,B, C≤20)。接下来有A×B×C个整数,即各个废料块的价值,每个废料块的价值的绝对值不超过231。如果给每个废料块赋予一个空间坐标(一个角为(1,1,1),对角线的另一端为(A,B,C)),则这些废料块在输入文件中的出现顺序为:(1,1,1),(1,1,2), …, (1,1,C), (1,2,1), …,(1,2,C), …, (1,B,C), …, (2,1,1), …, (2,B,C), …, (A,B,C)。

    【输出格式】

    对于每组数据,输出最大子长方体的价值和。


    贴下刘汝佳老师的解释

    还是老规矩,先想一个正确但低效的方法。枚举x,y,z的上下界x1, x2, y1, y2, z1, z2,然后比较这O(n6)个长方体的价值和,而每个长方体还需要O(n3)时间累加出价值和,所以总时间复杂度为O(n9),即使对于n≤20这样的规模,也太大了。
    解决高维问题的常见思路是降维。让我们先来看看本题的二维情况:给定一个数字矩阵,求一个和最大的连续子矩阵。借用上题的思路,我们枚举上下边界y1和y2(规定x从左到右递增,y从上到下递增),则问题转化为了一维问题,如图1-32所示。
    
    
    ?	?	?	?	?
    ?	?	?	?	?
    -1	-2	8	3	1
    -5	1	2	-7	-1
    	4	-2	10	-3	11
    1	3	2	-4	5
    9	-4	-2	5	6
    ?	?	?	?	?
    图  1-32
    注意,右图这个一维问题中的一个元素对应左图4个灰色格子的数之和。比如,(-1)+(-5)+1+9=4,(-2)+1+3+(-4)=-2等。
    为了节省时间,这4个元素不能再用一重循环来累加得到,否则时间复杂度会变成O(n4)。我们得想办法让这些元素可以在O(1)时间内得到,这样,二维问题才能在O(n3)时间内解决。
    
    
    解决方法仍然是前面曾多次使用的递推法:设sum(x,y1,y2)表示满足y1≤y≤y2的所有格子(x,y)里的数之和,则当y1<y2时,sum(x,y1,y2)=sum(x,y1,y2-1)+A[x][y2]。这样,可以事先在O(n3)时间内算出整个sum数组,则所有一维问题中的元素都可以在O(1)时间内得到,完整的二维问题在O(n3)时间内得到了解决。
    
    
    上述两种方法都可以很方便地推广到三维情形,时间复杂度为O(n5)。因为三维情况下的n很小,因此前面所说的空间问题并不严重。下面是算法一的完整代码,它用三维数组S保存以(x,y,z)为“右下角”的长方体的元素和。代码效率不算高,但读者很容易把它推广到四维或更高维的情形。
    

    简单易懂 就不多说了


    贴代码:

    	#include <cstdio>  
    	#include <cstdlib>  
    	#include <cmath>  
    	#include <cstring>  
    	#include <ctime>  
    	#include <algorithm>  
    	#include <iostream>
    	#include <sstream>
    	#include <string>
    	#define oo 0x13131313
    	const int maxn=22;   
    	using namespace std;
    	int A,B,C;
    	long long STEP1[maxn][maxn][maxn];
    	long long ans=-9223372036854775100;
    	void input()
    	{
    		cin>>A>>B>>C;
    		ans=-9223372036854775100;
    		for(int i=1;i<=A;i++)
    		 for(int j=1;j<=B;j++)
    		  for(int k=1;k<=C;k++)
    		  {
    		  	cin>>STEP1[i][j][k];
    		  }
    		for(int i=1;i<=A;i++)
    		 for(int j=1;j<=B;j++)
    		  for(int k=1;k<=C;k++)
    		  {
    		  		STEP1[i][j][k]+=STEP1[i-1][j][k];
    		  }
    	}
    	long long STEP3[maxn];
    	long long STEP2[maxn][maxn];
    	void get_STEP3(int a,int b)
    	{
    		for(int i=1;i<=C;i++)
    		 STEP3[i]=STEP2[b][i]-STEP2[a-1][i];
    		for(int i=1;i<=C;i++)
    		{
    			if(STEP3[i-1]>0)
    				STEP3[i]+=STEP3[i-1];
    			if(STEP3[i]>ans) ans=STEP3[i];
    		}
    	}
    	void get_STEP2(int a,int b)
    	{
    		for(int i=1;i<=B;i++)
    		 for(int j=1;j<=C;j++)
    		 STEP2[i][j]=STEP1[b][i][j]-STEP1[a-1][i][j];
    		for(int i=1;i<=B;i++)
    		 for(int j=1;j<=C;j++)
    		  STEP2[i][j]+=STEP2[i-1][j];
    		for(int i=1;i<=B;i++)
    		 for(int j=i;j<=B;j++)
    		 {
    			 get_STEP3(i,j);
    		 }
    	}
    	void solve()
    	{
    		for(int i=1;i<=A;i++)
    		 for(int j=i;j<=A;j++)
    		 {
    		  	get_STEP2(i,j);
    		 }
    	}
    	int main()
    	{
    			//freopen("a.in","r",stdin);
    			//freopen("a.out","w",stdout);
    			int T;
    			cin>>T;
    			while(T--)
    			{
    				input();
    				solve();
    				cout<<ans<<endl;
    				if(T!=0) cout<<endl;
    			}
    		return 0;
    	}
    	  


  • 相关阅读:
    环境配置 | 安装Jupyter Notebook及jupyter_contrib_nbextensions库实现代码自动补全
    环境配置 | mac环境变量文件.bash_profile相关
    Django | 解决“(1146, "Table 'mydb.django_session' doesn't exist")”报错的方法
    Django | pycharm 提示 unresolved attribute referene 'objects' for class 'xxxx'
    站点中添加企业qq的几种方式
    div自适应高度
    SVN服务器搭建和使用(三)
    SVN服务器搭建和使用(二)
    SVN服务器搭建和使用(一)
    宽度为100%,缩小窗口,右侧的区域背景图片变成空白
  • 原文地址:https://www.cnblogs.com/zy691357966/p/5480441.html
Copyright © 2011-2022 走看看