1. 程式人生 > >【BZOJ3619】璀燦光華(ZJOI2014)-思維+建圖

【BZOJ3619】璀燦光華(ZJOI2014)-思維+建圖

測試地址:璀燦光華 (BZOJ沒有題面,所以貼了洛谷的測試地址) 做法: 本題需要用到思維+建圖。 首先吐槽一下,這個題目名字是不是應該叫“璀璨”啊…算了算了,強省大佬自有用意,我這種閱讀理解00分選手還是不要妄加猜測了… 注意到nn很小,可以直接暴力列舉,O(a6n)O(a\cdot 6^n)解決這個問題。這個題最難的地方在於,如何通過這些點的相互連線,得出每個點在立方體中的座標。 首先,度數為33的點肯定是立方體的角,我們隨便拿一個角作為座標系的原點,我們發現原點在這樣的立方體圖中和某個點的最短路,就等於空間座標系中原點和這個點的曼哈頓距離,也即xi+yi+zix_i+y_i+z_i

。我們可以試圖找到原點在立方體某一面對角線上的另一個端點,令這個點座標為(0,a1,a1)(0,a-1,a-1),找的方法就是找前面那個曼哈頓距離等於2(a1)2(a-1),而且度數為33的點。那麼再以這個點為起點處理出最短路,我們又可以得到每個點的一個曼哈頓距離:xi+(a1yi)+(a1zi)x_i+(a-1-y_i)+(a-1-z_i)。有了這兩個距離,顯然這兩個距離加起來等於2(a1)+2xi2(a-1)+2x_i,這樣我們就能算出一個座標了,同理可算出另一個座標y
iy_i
,於是ziz_i只要從第一個曼哈頓距離裡減一減就出來了。 算出來了編號到座標之間的轉換,就可以直接暴力列舉得到答案了,我們就解決了這一題。 以下是本人程式碼:

#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; }