这道题目网上的标签一般都是“码农题”,但是我的算法感觉编程复杂度挺低的....
关键是确定每个点的坐标,然后就是暴力+卡常数了
一开始想过分各种情况讨论,十分繁琐了。
这道题关键是发现一个点的度数和它到若干关键点的距离对这个点的坐标的影响
首先确定一个原点(度数为3),然后从点BFS,计算到每个点经过的点的个数,我们发现,度数为3而且与原点有$2n - 1$个点的点,是和原点在同一个平面而且是原点对角线上的另一个点
这样的点一共有3个,每一个和原点都能确定所有点的一个维度,只要对它进行BFS,然后若一个点到原点是$S[i]$,到关键点是$T[i]$,那么该维度就是$frac{S[i] + T[i] - 2n}{2} + 1$
于是我们做3遍就可以确定所有点的坐标了。额,因为后面的暴力想多卡点常数,把暴力部分的代码改丑了
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 #include <algorithm> 6 #include <ctime> 7 using namespace std; 8 #define rep(i, l, r) for (int i = l; i <= r; i++) 9 #define drep(i, r, l) for (int i = r; i >= l; i--) 10 typedef long long ll; 11 const int N = 72, M = N * N * N; 12 int n, m, f[N][N][N], cnt[N][N][N], g[M], S[M], T[M], h[M], p[M][4], rt, sz, a[N], End; 13 int head[M], tot, Size[M]; 14 int Max, Min, cur; 15 int tx[6] = {1, -1, 0, 0, 0, 0}; 16 int ty[6] = {0, 0, 1, -1, 0, 0}; 17 int tz[6] = {0, 0, 0, 0, 1, -1}; 18 struct Edge{int next, node;}e[M * 6]; 19 inline void add(int x, int y) 20 { 21 e[++tot].next = head[x], head[x] = tot, e[tot].node = y; 22 } 23 double t1, t2; 24 int getint() 25 { 26 End = 0; 27 char c; int num = 0; 28 for (c = getchar(); !isdigit(c); c = getchar()) if (c == ' ') return -1; 29 for (; isdigit(c); c = getchar()) num = num * 10 + c - '0'; 30 if (c == ' ') End = 1; 31 return num; 32 } 33 void BFS(int s, int *d) 34 { 35 rep(i, 1, m) d[i] = 0; 36 int l = 1, r = 1; h[1] = s; 37 d[s] = 1; 38 while (l <= r) 39 { 40 int u = h[l++]; 41 for (int i = head[u], v; v = e[i].node, i; i = e[i].next) 42 if (!d[v]) 43 d[v] = d[u] + 1, h[++r] = v; 44 } 45 } 46 void calc(int s, int w) 47 { 48 BFS(s, T); 49 rep(i, 1, m) 50 { 51 p[i][w] = ((S[i] + T[i]) - (2 * n)) / 2 + 1; 52 } 53 } 54 void build() 55 { 56 BFS(rt, S); int w = 0; 57 rep(i, 1, m) 58 if (S[i] == 2 * n - 1 && Size[i] == 3) calc(i, ++w); 59 rep(i, 1, m) 60 f[p[i][1]][p[i][2]][p[i][3]] = i; 61 } 62 void dfs(int d) 63 { 64 if (d == sz + 1) 65 { 66 Max = max(Max, cur); 67 Min = Min < 0 ? cur : min(cur, Min); 68 return; 69 } 70 rep(i, 0, 5) 71 { 72 if (i <= 1) 73 { 74 int x = p[a[d]][1], y = p[a[d]][2], z = p[a[d]][3]; 75 for(; x >= 1 && x <= n; x += tx[i]) 76 { 77 int &u = cnt[x][y][z]; u++; 78 if (u == 1) cur += g[f[x][y][z]]; 79 } 80 dfs(d + 1); 81 x = p[a[d]][1]; 82 for(; x >= 1 && x <= n; x += tx[i]) 83 { 84 int &u = cnt[x][y][z]; u--; 85 if (u == 0) cur -= g[f[x][y][z]]; 86 } 87 } 88 else if (i <= 3) 89 { 90 int x = p[a[d]][1], y = p[a[d]][2], z = p[a[d]][3]; 91 for(; y >= 1 && y <= n; y += ty[i]) 92 { 93 int &u = cnt[x][y][z]; u++; 94 if (u == 1) cur += g[f[x][y][z]]; 95 } 96 dfs(d + 1); 97 y = p[a[d]][2]; 98 for(; y >= 1 && y <= n; y += ty[i]) 99 { 100 int &u = cnt[x][y][z]; u--; 101 if (u == 0) cur -= g[f[x][y][z]]; 102 } 103 } 104 else 105 { 106 int x = p[a[d]][1], y = p[a[d]][2], z = p[a[d]][3]; 107 for(; z >= 1 && z <= n; z += tz[i]) 108 { 109 int &u = cnt[x][y][z]; u++; 110 if (u == 1) cur += g[f[x][y][z]]; 111 } 112 dfs(d + 1); 113 z = p[a[d]][3]; 114 for(; z >= 1 && z <= n; z += tz[i]) 115 { 116 int &u = cnt[x][y][z]; u--; 117 if (u == 0) cur -= g[f[x][y][z]]; 118 } 119 } 120 } 121 } 122 void solve() 123 { 124 build(); 125 cur = 0; Max = 0; Min = -1; dfs(1); 126 printf("%d %d ", Min, Max); 127 } 128 int main() 129 { 130 #ifndef ONLINE_JUDGE 131 freopen("glitter.in", "r", stdin); 132 //freopen("glitter.out", "w", stdout); 133 #endif 134 135 scanf("%d", &n); m = n * n * n; 136 rep(i, 1, m) 137 { 138 scanf("%d", &g[i]); if (!g[i]) a[++sz] = i; 139 rep(j, 1, 6) 140 { 141 int x = getint(); 142 if (x == -1) break; 143 add(i, x); Size[i]++; 144 if (End) break; 145 } 146 if (Size[i] == 3) rt = i; 147 } 148 solve(); 149 #ifndef ONLINE_JUDGE 150 fclose(stdin); fclose(stdout); 151 #endif 152 return 0; 153 }