Garbage Heap
Farmer John has a heap of garbage formed in a rectangular parallelepiped.
It consists of AxBxC garbage pieces each of which has a value. The value of a piece may be 0, if the piece is neither profitable nor harmful, and may be negative which means that the piece is not just unprofitable, but even harmful (for environment).
The farmer thinks that he has too much harmful garbage, so he wants to decrease the heap size, leaving a rectangular nonempty parallelepiped of smaller size cut of the original heap to maximize the sum of the values of the garbage pieces in it. You have to find the optimal parallelepiped value. (Actually, if any smaller parallelepiped has value less than the original one, the farmer will leave the original parallelepiped).
The first line of the input contains the number of the test cases, which is at most 15. The descriptions of the test cases follow. The first line of a test case description contains three integers A, B, and C (1 ≤ A, B, C ≤ 20). The next lines contain A·B·C numbers, which are the values of garbage pieces. Each number does not exceed 2^31 by absolute value. If we introduce coordinates in the parallelepiped such that the cell in one corner is (1,1,1) and the cell in the opposite corner is (A,B,C), then the values are listed in the order
For each test case in the input, output a single integer denoting the maximal value of the new garbage heap. Print a blank line between test cases.
Sample Input
1
2 2 2
-1 -2 0 -3 -2 -1 1 5
Sample Output
6
一上午都在调这个题,真是哭惨了,因为输入数据保证每块Garbage的value的绝对值不小于2^31,而int类型的范围是[-2^31,2^31-1]所以必须用lld来读入数据。
再就没有什么需要注意的了,这道题和前几道关于子序列的题目可以说成为了一个体系,如果前几道题认真啃透的话,那么这道题就会变得很简单,难点在于,清晰的将容斥原理应用正确。
另外要相信自己,网上的数据不一定就是对的。
自我感觉Liu的代码是有点繁琐的,他多写了几个调用函数虽然让程序简单了一些,但是整体看的确有点冗长繁琐,如果直接利用容斥原理的话,也能使代码很清晰。
附代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define clr(x) (memset(x,0,sizeof(x)))
#define REP(i,j,k) for(int i=(j);i<=(k);i++)
#define ll long long int
#define MAXN (20+5)
#define OO ((ll)1<<60)
int A,B,C;
ll s[MAXN][MAXN][MAXN];
int main(){
int total;
scanf("%d",&total);
while(total--){
clr(s);
scanf("%d%d%d",&A,&B,&C);
REP(i,1,A) REP(j,1,B) REP(k,1,C){
ll x;
scanf("%lld",&x);
s[i][j][k]=x+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,1,A) REP(j,1,B) REP(k,1,C){printf("%d\n",s[i][j][k]);}
ll ans=-OO;
REP(zd,1,C) REP(zu,zd,C){
REP(yd,1,B) REP(yu,yd,B){
ll tmp=0;
REP(x,1,A){
ll now=s[x][yu][zu]-s[x][yu][zd-1]-(s[x][yd-1][zu]-s[x][yd-1][zd-1]);
ans=max(ans,now-tmp);
tmp=min(tmp,now);
}
}
}
printf("%lld\n",ans);
if(total)printf("\n");
}
return 0;
}