题意:
用1*1*1的小立方体叠成一个A*B*C立方体,然后给出N个小立方体的中心(x,y,z)然后依次拿走该立方体,在拿走N个立方体后求剩下立方结合体的表面积。
思路:
首先算出当前立方体的表面积记为sum,然后判断现在要拿走的立方体有多少个面记为s1已经被算在里面了,即可得出没有算的面为6-s1,就可以知道拿走这个立方体后,丢失了s1个面,然后得到了6-s1的面,;但你每次拿走该立方体时必须要考虑它与之前已经拿走的立方体是否相邻,然后记录相邻的个数s,即当前表面积为sum +6-2*s1;
代码:
#include<cstdio>
#include <cmath>
using namespace std;
#define maxn 1111
typedef long long LL;
struct point
{
int x,y,z;
}points[maxn];
int main()
{
#ifdef CDZSC_June
freopen("t.txt", "r", stdin);
#endif
int n,s;
LL sum,s1,a,b,c;
while(~scanf("%lld%lld%lld%d",&a,&b,&c,&n))
{
sum = 2*a*b + 2*a*c + 2*c*b;//计算当前表面积
for(int i = 0; i<n; i++)
{
s = s1 = 0;
scanf("%d%d%d",&points[i].x,&points[i].y,&points[i].z);
if(points[i].x == a -1 || points[i].x == -1){//判断前面的面是否被算在sum里面了
s1++;
}
if(points[i].x == a || !points[i].x){//判断后面的面是否被算在sum里面了
s1++;
}
if(points[i].y == b -1 || points[i].y== -1){//判断右面的面是否被算在sum里面了
s1++;
}
if(points[i].y == b || !points[i].y){//判断左面的面是否被算在sum里面了
s1++;
}
if(points[i].z == c -1 || points[i].z == -1 ){//判断上面的面是否被算在sum里面了
s1++;
}
if(points[i].z == c || !points[i].z){//判断下面的面是否被算在sum里面了
s1++;
}
for(int j = 0; j<i; j++)
{//判断当前立方体与之前已经拿走的立方体是否相邻
if(i!=j && ((abs(points[j].x - points[i].x) == 1 && points[j].y == points[i].y && points[j].z == points[i].z)
|| (abs(points[j].y - points[i].y) == 1 && points[j].x == points[i].x && points[j].z == points[i].z)
|| (abs(points[j].z - points[i].z) == 1 && points[j].y == points[i].y && points[j].x == points[i].x))){
s++;
}
}
sum += (6-2*s1-2*s);
}
printf("%lld\n",sum);
}
return 0;
}