传送门:点击打开链接
题意:给一个长方体,边长分别为A,B,C。然后给n个空间位置,表示在这个位置挖一个边长为1的小正方体。求挖完n个位置后的这个立体图形的表面积。
思路:看起来非常复杂,其实仔细想想非常非常的简单。
首先,对于小正方体,有6个面,我们先考虑下相对的两个面。
在一个相对的面里,如果两边都存在实体,那么挖走这个小正方体后表面积会+2
在一个相对的面里,只有一边都存在实体,那么挖走这个小正方体后表面积不变
在一个相对的面里,两边都被挖走了,那么挖走这个小正方体后表面积会-2
所以,我只要讨论,某个位置是否是空着的就行了,很明显用set就能维护。
所以这道题就基本搞定了、。
#include<map> #include<set> #include<cmath> #include<ctime> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<bitset> #include<string> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #define fuck(x) cout<<"["<<x<<"]" #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w+",stdout) //#pragma comment(linker, "/STACK:102400000,102400000") using namespace std; typedef long long LL; const int MX = 1e3 + 5; struct Node { int x, y, z; Node() {} Node(int _x, int _y, int _z) { x = _x; y = _y; z = _z; } bool operator<(const Node &P) const { if(x == P.x) { if(y == P.y) return z < P.z; return y < P.y; } return x < P.x; } }; LL A, B, C; multiset<Node>S; bool check(int x, int y, int z) { if(x < 1 || x > A || y < 1 || y > B || z < 1 || z > C) return false; if(S.count(Node(x, y, z))) return false; return true; } int f(int x) { if(x == 0) return -2; if(x == 1) return 0; return 2; } int main() { int n; //FIN; while(~scanf("%lld%lld%lld%d", &A, &B, &C, &n)) { LL ans = 2 * A * B + 2 * A * C + 2 * B * C; S.clear(); for(int i = 1; i <= n; i++) { int x, y, z; scanf("%d%d%d", &x, &y, &z); x++; y++; z++; ans += f(check(x - 1, y, z) + check(x + 1, y, z)); ans += f(check(x, y - 1, z) + check(x, y + 1, z)); ans += f(check(x, y, z - 1) + check(x, y, z + 1)); S.insert(Node(x, y, z)); } printf("%lld\n", ans); } return 0; }