[Zjoi2014]璀灿光华

这道题目网上的标签一般都是“码农题”,但是我的算法感觉编程复杂度挺低的....

关键是确定每个点的坐标,然后就是暴力+卡常数了

一开始想过分各种情况讨论,十分繁琐了。

这道题关键是发现一个点的度数和它到若干关键点的距离对这个点的坐标的影响

首先确定一个原点(度数为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 == '\n') return -1;
 29     for (; isdigit(c); c = getchar()) num = num * 10 + c - '0';
 30     if (c == '\n') 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\n", 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 }
BZOJ3619

 

posted on 2015-04-24 09:58  Dyzerjet  阅读(435)  评论(0编辑  收藏  举报