【BZOJ3619】璀燦光華(ZJOI2014)-思維+建圖
阿新 • • 發佈:2018-12-19
測試地址:璀燦光華 (BZOJ沒有題面,所以貼了洛谷的測試地址) 做法: 本題需要用到思維+建圖。 首先吐槽一下,這個題目名字是不是應該叫“璀璨”啊…算了算了,強省大佬自有用意,我這種閱讀理解分選手還是不要妄加猜測了… 注意到很小,可以直接暴力列舉,解決這個問題。這個題最難的地方在於,如何通過這些點的相互連線,得出每個點在立方體中的座標。 首先,度數為的點肯定是立方體的角,我們隨便拿一個角作為座標系的原點,我們發現原點在這樣的立方體圖中和某個點的最短路,就等於空間座標系中原點和這個點的曼哈頓距離,也即。我們可以試圖找到原點在立方體某一面對角線上的另一個端點,令這個點座標為,找的方法就是找前面那個曼哈頓距離等於,而且度數為的點。那麼再以這個點為起點處理出最短路,我們又可以得到每個點的一個曼哈頓距離:。有了這兩個距離,顯然這兩個距離加起來等於,這樣我們就能算出一個座標了,同理可算出另一個座標,於是只要從第一個曼哈頓距離裡減一減就出來了。 算出來了編號到座標之間的轉換,就可以直接暴力列舉得到答案了,我們就解決了這一題。 以下是本人程式碼:
#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;
}