金先生有一个女朋友没名字。她勤劳勇敢、智慧善良。金先生很喜欢她。为此,金先生用 a3 块1×1×1的独特的水晶制作了一个边长为 a 的水晶立方体,他要将这个水晶立方体送给他见过最单纯善良的她。
由于水晶立方体太太,不好运送,金先生还是将它拆开来送出。他相信拼好这个水晶立方难不倒聪明的她。
没名字收到了礼物后果然不一会儿就根据说明将水晶立方体拼好了。没名字发现,有 n 块水晶在漆黑安静的夜晚会随机以等概率向上下左右前后六个方向的一个发出光。被光照到的水晶显得格外好看。没名字给每一块不会发光的水晶定义了一个好看程度。水晶立方体在夜晚中的好看程度就是每块被光照到的水晶的好看程度之和。没名字想知道,水晶立方体在夜晚中的好看程度的最小值和最大值。
输入格式
第一行是 a,表示水晶立方体的边长。
接下来 a3 行,每行若干整数。
第一个数 gi 表示第 i 块水晶的好看程度。如果 gi=0,代表这块水晶会发光。接下来 3∼6个整数,代表与这块水晶有共同面的水晶编号。
int cnt; inlinevoidadd_edge(int f, int t) { e[++cnt].nxt = first[f]; first[f] = cnt; e[cnt].to = t; }
int dirx[] = {1, -1, 0, 0, 0, 0}; int diry[] = {0, 0, 1, -1, 0, 0}; int dirz[] = {0, 0, 0, 0, 1, -1};
int dep[maxn];//" 好看程度 " int vis[maxn]; int minn = inf; int maxx = -inf; int ll[10];// 会发光的水晶的编号 int ddn[maxn];// 度数 int zl;// 这是个 ddn 的 cnt int mmap[73][73][73];
structzb { int x, y, z; } poi[maxn];
#define pan (x > 0 && x <= tn && y > 0 && y <= tn && z > 0 && z <= tn) #define nxxt x += dirx[i], y += diry[i], z += dirz[i]
inlineintgetans(int i, zb a)// 能加多少 " 好看程度 " { int ans = 0; int x = a.x, y = a.y, z = a.z; for(; pan; nxxt) if(!vis[mmap[x][y][z]]++)// 由于待会儿回溯时要删除,所以懒到家的我就直接用 ++,-- 代替记录了 ans += dep[mmap[x][y][z]]; return ans; }
inlinevoiddelvis(int i, zb a)// 回溯时把 dfs 前加的 vis 删除 { int x = a.x, y = a.y, z = a.z; for(; pan; nxxt) vis[mmap[x][y][z]]--; }
inlinevoiddfs(int now, int ans)// 大力枚举所有情况 { if(now > zl) { minn = min(minn, ans); maxx = max(maxx, ans); return; } for(int i = 0; i < 6; ++i) { dfs(now+1, ans + getans(i, poi[ll[now]])); delvis(i, poi[ll[now]]); } }
int dist[4][maxn]; int di[4]; bool viss[maxn];
inlinevoidbfs(int id)// 求最短路 { memset(viss, 0, sizeof(viss)); queue<int> q; int from = di[id]; viss[from] = true; q.push(from); while(!q.empty()) { int now = q.front(); q.pop(); for(int i = first[now]; i; i = e[i].nxt) { int to = e[i].to; if(!viss[to]) { viss[to] = true; dist[id][to] = dist[id][now] + 1; q.push(to); } } } }