题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4941
题目大意:
有一个l*w*h的立方体,可以分为l*w*h个单位立方体,每个单位立方体上有一个非负数。
相邻的两个立方体可以同时减去或加上一个整数任意次。
求是否可以使所有立方体上的数为零。
题目思路:
首先可以确定的是,(*)要减去的数是所有的数之和。
并且要对两个相邻的单位方块进行操作,假设某一个方块的数大于与它相邻的所有方块之和,如果要使这个方块能被减为0,要如何做到呢?
那么显然与它相邻的数要向其他地方借数。
为了方便我们构造如下图:
a1 a2 a3 a4
a5 a6 a7 a8
a9 b1 b2 b3
设a2 > a1+a3+a6
那么显然a1,a3,a6要向a5,b1,a7,a4借数,才能使得a2被减为0,
而被借的数,显然要承担的值就为a2 -(a1+a3+a6),即值被转移了。
通过上面的例子我们可以知道,设某一个值的坐标为(i,j,k),那么该值可以向所有坐标为(x+y+z)且
(x+y+z)%2==(i+j+k)%2的转移值。
又由(*)可知,不管对值怎么进行转移,要减去多少数始终只会减去多少数。
也就是说只要满足sum[(x+y+z)%2==0] = sum[(x+y+z)%2==1]即可。
代码:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll __int64
#define ls rt<<1
#define rs ls|1
#define lson l,mid,ls
#define rson mid+1,r,rs
#define middle (l+r)>>1
#define clr_all(x,c) memset(x,c,sizeof(x))
#define clr(x,c,n) memset(x,c,sizeof(x[0])*(n+1))
#define eps (1e-8)
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define PI (acos(-1.0))
#pragma comment(linker, "/STACK:102400000,102400000")
template <class T> T _max(T x,T y){return x>y? x:y;}
template <class T> T _min(T x,T y){return x<y? x:y;}
template <class T> T _abs(T x){return (x < 0)? -x:x;}
template <class T> T _mod(T x,T y){return (x > 0)? x%y:((x%y)+y)%y;}
template <class T> void _swap(T &x,T &y){T t=x;x=y;y=t;}
template <class T> void getmax(T& x,T y){x=(y > x)? y:x;}
template <class T> void getmin(T& x,T y){x=(x<0 || y<x)? y:x;}
int TS,cas=1;
const int M=60000+5;
int l,w,h,c[2],a;
void run(){
int i,j,k;
c[0]=c[1]=0;
for(i=0;i<l;i++)
for(j=0;j<w;j++)
for(k=0;k<h;k++)
scanf("%d",&a),c[(i+j+k)&1]+=a;
printf("%s\n",c[0]==c[1]? "Yes":"No");
}
void preSof(){
}
int main(){
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
preSof();
//run();
while((~scanf("%d%d%d",&l,&w,&h))) run();
//for(scanf("%d",&TS);cas<=TS;cas++) run();
return 0;
}