UVA10755 Garbage Heap

链接

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1696

题解1

我直接用的大暴力,预处理前缀和,然后枚举左下角和右上角,容斥一下,统计最大值,160ms过
但是,我为什么 W A 了一整天呢?
因为原题中有这句话:这里写图片描述,而刘汝佳的书上却没有!
我现在想摔书啊!
时间复杂度 O ( n 6 )

题解2

看了看刘汝佳的算法,思路一如既往的清奇
他的思路是枚举两个平面,然后把这两个平面之间夹的立方体压起来,变成二维。具体地说,就是枚举 z 1 , z 2 ,然后用这两个面去切长方体,切出来的长方体所有点的纵坐标都在 z 1 , z 2 之间,把横纵坐标相同的求个和,然后放到二维矩阵里去,现在矩阵中每个数对应原来立方体中一竖排的和。
然后再枚举 y 1 , y 2 ,用同样的方式压掉 y 坐标,现在转化成一维求最大连续子段和。直接 O ( n )
这样算下来是 O ( n 5 ) ,确实比我的大暴力快一点,实测 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;
}

猜你喜欢

转载自blog.csdn.net/fsahfgsadhsakndas/article/details/81071333