测试地址:璀灿光华
(BZOJ没有题面,所以贴了洛谷的测试地址)
做法: 本题需要用到思维+建图。
首先吐槽一下,这个题目名字是不是应该叫“璀璨”啊…算了算了,强省大佬自有用意,我这种阅读理解
0
0
0分选手还是不要妄加猜测了…
注意到
n
n
n很小,可以直接暴力枚举,
O
(
a
⋅
6
n
)
O(a\cdot 6^n)
O(a⋅6n)解决这个问题。这个题最难的地方在于,如何通过这些点的相互连接,得出每个点在立方体中的坐标。
首先,度数为
3
3
3的点肯定是立方体的角,我们随便拿一个角作为坐标系的原点,我们发现原点在这样的立方体图中和某个点的最短路,就等于空间坐标系中原点和这个点的曼哈顿距离,也即
x
i
+
y
i
+
z
i
x_i+y_i+z_i
xi+yi+zi。我们可以试图找到原点在立方体某一面对角线上的另一个端点,令这个点坐标为
(
0
,
a
−
1
,
a
−
1
)
(0,a-1,a-1)
(0,a−1,a−1),找的方法就是找前面那个曼哈顿距离等于
2
(
a
−
1
)
2(a-1)
2(a−1),而且度数为
3
3
3的点。那么再以这个点为起点处理出最短路,我们又可以得到每个点的一个曼哈顿距离:
x
i
+
(
a
−
1
−
y
i
)
+
(
a
−
1
−
z
i
)
x_i+(a-1-y_i)+(a-1-z_i)
xi+(a−1−yi)+(a−1−zi)。有了这两个距离,显然这两个距离加起来等于
2
(
a
−
1
)
+
2
x
i
2(a-1)+2x_i
2(a−1)+2xi,这样我们就能算出一个坐标了,同理可算出另一个坐标
y
i
y_i
yi,于是
z
i
z_i
zi只要从第一个曼哈顿距离里减一减就出来了。
算出来了编号到坐标之间的转换,就可以直接暴力枚举得到答案了,我们就解决了这一题。
以下是本人代码:
#include <bits/stdc++.h>
using namespace std;
const int inf=1000000000;
int a,n,c[350010]={0},dis[350010][2]={0};
int x[350010],y[350010],z[350010];
int val[75][75][75],p[10][2]={0},q[350010],h,t;
int mv[6][3]={{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};
int mxans=0,mnans=inf,nowans=0;
int vis[75][75][75]={0};
vector<int> e[350010];
char read(int &s)
{
s=0;
char c;
c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') s=s*10+c-'0',c=getchar();
return c;
}
void bfs(int s,bool type)
{
h=t=1;
q[1]=s;
for(int i=1;i<=a*a*a;i++)
dis[i][type]=inf;
dis[s][type]=0;
while(h<=t)
{
int v=q[h++];
for(int i=0;i<e[v].size();i++)
{
int y=e[v][i];
if (dis[y][type]==inf)
{
dis[y][type]=dis[v][type]+1;
q[++t]=y;
}
}
}
}
void dfs(int step)
{
if (step==p[0][0])
{
mxans=max(mxans,nowans);
mnans=min(mnans,nowans);
return;
}
step++;
for(int i=0;i<6;i++)
{
int nowx=x[p[step][0]],nowy=y[p[step][0]],nowz=z[p[step][0]];
while(nowx>=0&&nowx<a&&nowy>=0&&nowy<a&&nowz>=0&&nowz<a)
{
if (!vis[nowx][nowy][nowz]) nowans+=val[nowx][nowy][nowz];
vis[nowx][nowy][nowz]++;
nowx+=mv[i][0],nowy+=mv[i][1],nowz+=mv[i][2];
}
dfs(step);
nowx=x[p[step][0]],nowy=y[p[step][0]],nowz=z[p[step][0]];
while(nowx>=0&&nowx<a&&nowy>=0&&nowy<a&&nowz>=0&&nowz<a)
{
if (vis[nowx][nowy][nowz]==1) nowans-=val[nowx][nowy][nowz];
vis[nowx][nowy][nowz]--;
nowx+=mv[i][0],nowy+=mv[i][1],nowz+=mv[i][2];
}
}
}
int main()
{
read(a);
for(int i=1;i<=a*a*a;i++)
{
read(c[i]);
if (c[i]==0) p[++p[0][0]][0]=i;
int nxt;
char C;
C=read(nxt);
e[i].push_back(nxt);
while(C!='\n'&&C!=EOF) C=read(nxt),e[i].push_back(nxt);
if (e[i].size()==3) p[++p[0][1]][1]=i;
}
bfs(p[1][1],0);
bool flag=0;
for(int i=2;i<=8;i++)
if (dis[p[i][1]][0]==2*(a-1))
{
bfs(p[i][1],1);
for(int j=1;j<=a*a*a;j++)
{
if (!flag) x[j]=(dis[j][0]+dis[j][1]-2*(a-1))>>1;
else y[j]=(dis[j][0]+dis[j][1]-2*(a-1))>>1;
}
if (!flag) flag=1;
else break;
}
for(int i=1;i<=a*a*a;i++)
{
z[i]=dis[i][0]-x[i]-y[i];
val[x[i]][y[i]][z[i]]=c[i];
}
dfs(0);
printf("%d %d",mnans,mxans);
return 0;
}