【降维解法:最大字段和->最大子矩阵和->最终版最大子长方体和】【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个废料块组成,每个废料块都有一个价值,可正可负。现在要在这个长方体上选择一个子长方体,使组成这个子长方体的废料块的价值之和最大。
【输入格式】
输入的第一行为数据组数T(T≤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;
}
【降维解法:最大字段和->最大子矩阵和->最终版最大子长方体和】【UVA10755】Garbage Heap的更多相关文章
- AI学习---特征工程【特征抽取、特征预处理、特征降维】
学习框架 特征工程(Feature Engineering) 数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已 什么是特征工程: 帮助我们使得算法性能更好发挥性能而已 sklearn主 ...
- SQLSERVER查询整个数据库中某个特定值所在的表和字段的方法
这几天有业务部门需要使用一个SAP B1老系统 中的报表,但是由于此报表没有加时间条件,导致一旦开始查询 就会导致B1系统异常退出.由于报表对应的SQL 是存在数据库中,所以想通过查找到这个报表的S ...
- 使用 SQL Server 的 uniqueidentifier 字段类型
原文:使用 SQL Server 的 uniqueidentifier 字段类型 SQL Server 自 2008 版起引入了 uniqueidentifier 字段,它存储的是一个 UUID, 或 ...
- JavaScript 的新特性:类的 #private 字段
这是什么,如何使用,为什么需要? 一边听“Noise Pollution” —— Portugal. The Man,一边阅读本文简直就是享受 JavaScript 标准的第二阶段(Stage 2)加 ...
- 八.Protobuf3更新消息类型(添加新的字段)
Protobuf3 更新消息类型 如果现有的消息类型不满足你的所有需求——例如,你希望消息格式有一个额外的字段——但是你仍然希望使用用旧格式创建的代码,别担心!在不破坏任何现有代码的情况下更新消息类型 ...
- Django-choices字段值对应关系(性别)-MTV与MVC科普-Ajax发json格式与文件格式数据-contentType格式-Ajax搭配sweetalert实现删除确认弹窗-自定义分页器-批量插入-07
目录 models 字段补充 choices 参数/字段(用的很多) MTV与MVC模型 科普 Ajax 发送 GET.POST 请求的几种常见方式 用 Ajax 做一个小案例 准备工作 动手用 Aj ...
- sqlserver 查询 字段
SELECT * FROM INFORMATION_SCHEMA.columns WHERE TABLE_NAME='MenuInfo' select * from sysobjects where ...
- Language Guide (proto3) | proto3 语言指南(八)未知字段和任意类型
未知字段和任意类型篇幅较少,因此将他们合并到本文进行描述. Unknown Fields - 未知字段 未知字段是格式良好的协议缓冲区序列化数据,表示解析器无法识别的字段.例如,当一个旧二进制代码解析 ...
- 爬虫总结_python
import sqlite3 Python 的一个非常大的优点是很容易写很容易跑起来,缺点就是很多不那么著名的(甚至一些著名的)程序和库都不像 C 和 C++ 那边那样专业.可靠(当然这也有动态类型 ...
随机推荐
- According to TLD or attribute directive in tag file, attribute value does not accept any expressions
1.错误描写叙述 2014-7-13 17:27:21 org.apache.jasper.compiler.TldLocationsCache tldScanJar 信息: At least one ...
- Git入门——基础知识问答
问题一:为什么要选择Git作为Android开发的版本控制工具? 答:1)git是android项目和社区的统一语言. 2)高通版本发布频繁,需要与平台及时同步,快速re ...
- Android 多线程断点下载(非原创)
1.服务器的CPU分配给每条线程的时间片相同,服务器带宽平均分配给每条线程,所以客户端开启的线程越多,就能抢占到更多的服务器资源,这里在客户端开启多个线程来从服务器下载资源 2.fragment_ma ...
- 0128——手势Gesture
UIGestureRecognizer: 1.locationinView 获取手势在某个视图里面的坐标位置 2.delegate监听手势的行为 3.state状态 开始:UIGestureRecog ...
- 循环小数 UVa202
输入整数a和b(0<=a<=3000,1<=b<=3000),输出a/b的循环小数表示以及循环节长度. 例如,a=5,b=43,小数表示为0.(1162790697674418 ...
- PHP方法的作用域
PHP支持6种方法作用域:public.private.protected.abstract.final和static,本文只讨论前5种作用域. public:公共作用域.(就像空气和阳光,天下公用) ...
- 微信订阅号开发之token验证后,自动回复消息功能做好,发送消息没有返回
相信很多人会跟我一样,token验证之后,发送消息给订阅号,没有消息返回. 以下,说一下我辛苦调试得到的解决办法: 首先,token验证: 自己写的token一直验证失败,找了好久,没有发现bug.实 ...
- 龙邱STM32单片机用J-LINK下载无法被识别的解决方法
问题如下: 按照正常步骤使用keil5给龙邱的stm32下载程序,SWD下载方式提示no cortex-m sw device found,JTAG方式提示no cortex-m device fou ...
- javascript跨域获取json数据
项目在开发过程中,用到了天气预报的功能,所以需要调用天气预报的api,一开始以为直接用ajax调用url就可以获取天气数据,结果涉及到了跨域的问题,这里做一个记录. 说到跨域,就得知道同源策略. 同源 ...
- information_schema.partitions 学习
1.partitions 表中的常用列说明: 1.table_schema:表所在的数据库名 2.table_name:表名 3.partition_method:表分区采用的分区方法 4.parti ...