链接
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1696
题解1
我直接用的大暴力,预处理前缀和,然后枚举左下角和右上角,容斥一下,统计最大值,160ms过
但是,我为什么
WA
W
A
了一整天呢?
因为原题中有这句话:,而刘汝佳的书上却没有!
我现在想摔书啊!
时间复杂度
O(n6)
O
(
n
6
)
题解2
看了看刘汝佳的算法,思路一如既往的清奇
他的思路是枚举两个平面,然后把这两个平面之间夹的立方体压起来,变成二维。具体地说,就是枚举
z1,z2
z
1
,
z
2
,然后用这两个面去切长方体,切出来的长方体所有点的纵坐标都在
z1,z2
z
1
,
z
2
之间,把横纵坐标相同的求个和,然后放到二维矩阵里去,现在矩阵中每个数对应原来立方体中一竖排的和。
然后再枚举
y1,y2
y
1
,
y
2
,用同样的方式压掉
y
y
坐标,现在转化成一维求最大连续子段和。直接
这样算下来是
O(n5)
O
(
n
5
)
,确实比我的大暴力快一点,实测
20ms
20
m
s
代码1
//大暴力
#include <cstdio>
#include <algorithm>
#include <cstring>
#define ll long long
#define maxn 25
#define clear(x) memset(x,0,sizeof(x))
#define rep(x,a,b) for(x=a;x<=b;x++)
using namespace std;
ll s[maxn][maxn][maxn], A, B, C, ans;
int main()
{
ll i, j, k, T, x, y, z, t;
for(scanf("%lld",&T);T--;)
{
clear(s);
ans=-(1ll<<60);
scanf("%lld%lld%lld",&A,&B,&C);
rep(i,1,A)rep(j,1,B)rep(k,1,C)scanf("%lld",s[i][j]+k);
rep(i,1,A)rep(j,1,B)rep(k,1,C)s[i][j][k]+=s[i-1][j][k]+s[i][j-1][k]+s[i][j][k-1]-s[i-1][j-1][k]-s[i-1][j][k-1]-s[i][j-1][k-1]+s[i-1][j-1][k-1];
rep(i,0,A-1)rep(j,0,B-1)rep(k,0,C-1)rep(x,i+1,A)rep(y,j+1,B)rep(z,k+1,C)
{
t=s[x][y][z]-s[i][y][z]-s[x][j][z]-s[x][y][k]+s[i][j][z]+s[i][y][k]+s[x][j][k]-s[i][j][k];
ans=max(t,ans);
}
printf("%lld\n",ans);
if(T)printf("\n");
}
return 0;
}
代码2
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
#define clear(x) memset(x,0,sizeof(x))
#define inf (1ll<<60)
#define ll long long
#define maxn 25
#define rep(x,a,b) for(x=a;x<=b;x++)
using namespace std;
ll s3[maxn][maxn][maxn], s2[maxn][maxn], s1[maxn], A, B, C, ans, m[maxn];
ll read(ll x=0)
{
char c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
return x*f;
}
void solve3();
void solve2();
void solve1();
void solve3()
{
ll i, j, k, z1, z2;
A=read(), B=read(), C=read();
clear(s3);
ans=-inf;
rep(i,1,A)rep(j,1,B)rep(k,1,C)s3[i][j][k]=read()+s3[i][j][k-1];
rep(z1,0,C-1)rep(z2,z1+1,C)
{
clear(s2);
rep(i,1,A)rep(j,1,B)s2[i][j]=s3[i][j][z2]-s3[i][j][z1];
solve2();
}
}
void solve2()
{
ll i, j, y1, y2;
rep(i,1,A)rep(j,1,B)s2[i][j]+=s2[i][j-1];
rep(y1,0,B-1)rep(y2,y1+1,B)
{
clear(s1);
rep(i,1,A)s1[i]=s2[i][y2]-s2[i][y1];
solve1();
}
}
void solve1()
{
ll i, j;
rep(i,1,A)s1[i]+=s1[i-1], m[i]=min(s1[i],m[i-1]), ans=max(ans,s1[i]-m[i-1]);
}
int main()
{
for(ll T=read();T--;)
{
solve3();
printf("%lld\n",ans);
if(T)printf("\n");
}
return 0;
}