【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,這樣我們就能算出一個座標了,同理可算出另一個座標yiy_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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章