POJ 1022 Packing Unit 4D Cubes【題解報告|4D紙老虎】

在這裏插入圖片描述
題目鏈接

題目大意:

這個題不算難,關鍵就是題意不好懂。這裏我不介紹背景,從輸入數據入手分析題意。

1.第一行表示樣例數目。每個樣例的第一行整數n表示樣例中含有的物體數目,其後n行描述n個物體。

2.描述一個物體用一行,一行包含9個整數。第一個表示該物體的編號(相當於名字)。剩下的8個數字2個一組,共四組。

3.每一組數字表示該物體在一個方向上的前後鄰居情況。(如果一個物體是二維平面的,我們認爲它有x,y兩個座標軸方向。如果物體是三維的,我們認爲它有x,y,z三個方向。本題中物體是四位的,用x,y,z,k代表它的四個方向)。

4.每一組中的第一個數表示這一方向上當前物體前面那個物體的編號。若當前物體的前面沒有物體,則這個數爲0.每一組中的第二個數表示這一方向上當前物體後面那個物體的編號,不存在則爲0。

5.例如樣例第三行:1 (2 3) (4 5) (6 7) (8 9) 。

含義如下:

當前物體編號爲1;

在x方向上,前面物體編號爲2,後面物體編號爲3;

在y方向上,前面物體編號爲4,後面物體編號爲5;

······

7.所給數據有 合法/不合法 兩種情況。數據合法的要求有兩個:

1)在某方向上,物體A 在 物體B 的前面,那麼 物體B 必須在 物體A 同方向的後面。乍看很費解,結合數

據清楚了。拿樣例來說,1號物體的描述中,第二個數字是2 ,表示 2號 在 1號 x方向的前面。那麼描

述 2號 物體時,表示 x軸 後面的數字必須是 1 ,即第三個數字是1。

2)給出的n個物體最終要連接成一個整體。(兩物體在某一方向相鄰,就認爲它們連接起來了)。這個可

以測試連通性解決。

8.若數據 不合法 ,輸出Inconsistent。若數據合法,則需要輸出 該整體 的 外接立方體(四維的)的體積。

9.關於體積的求解:當我們求三維立方體的體積時,就是把x,y,z三個方向上的長度乘起來。對於本題中的四維立方體,只需要把x,y,z,k四個軸方向上的最大長度乘起來就可以了。每一個物體在四個方向的長度都是1.

大致思路:

總體上利用深度優先搜索,從任意一個物體出發,看看是否能夠遍歷全部n個物體。若能,則滿足第二個合法條件。

在遍歷的同時檢查第一個合法條件。例如:從 物體A 出發進入 物體B 的瞬間,檢查 物體B 描述數據的對應位置是不是 物體A 的編號,如果是則進入B,否則直接返回 數據非法標誌。

在遍歷的同時還可以確定 外接立方體 在四個方向上的長度。任意挑選的第一個物體座標爲(0,0,0,0,),開兩個數組up[4],down[4],分別記錄在四個方向上的 最大座標值和最小座標值。若搜索到的第二個物體在當前物體x方向的前面,則它的座標爲(1,0,0,0),若在後面則是(-1,0,0,0)。即時比較更新up,down兩個數組的值,則遍歷結束後up-down就是所需四個方向的長度,乘起來就是答案。

//200K	0MS
#define inf 0x3f3f3f3f
#define ll long long
#define vec vector<int>
#define P pair<int,int>
#define MAX 1005

int T, cube[MAX][10], n, forw[5], backw[5], now[5], id, m, cnt = 0, sign;

//搜索到了編號爲k的物品
bool dfs(int k) {
	cube[k][0] = 1; cnt++;//0號位置表示該物品搜索過了

	for (int i = 1; i <= 8; i++) {
		int u = cube[k][i], v = cube[u][0];
		if (u == 0 || v == 1)continue;//已經訪問過了或者不存在
		int p = (i - 1) / 2, q = i % 2 ? 1 : -1;//1,3,5,7正面

		if (cube[u][i + q] != k)return false;//不滿足對稱性

		now[p] += q;//相應的位置加上座標,即下一個點的座標
		if (now[p] > forw[p])forw[p] = now[p];
		if (now[p] < backw[p])backw[p] = now[p];

		if (!dfs(u))return false;
		now[p] -= q;//回溯
	}
	return true;//遍歷完所有
}

int main() {
	scanf("%d", &T);
	while (T--) {
		memset(cube, 0, sizeof(cube));
		scanf("%d", &n);
		for (int i = 0; i < 5; i++)
			forw[i] = backw[i] = now[i] = 0;
		for (int i = 1; i <= n; i++) {
			scanf("%d", &m); id = m;
			for (int j = 1; j <= 8; j++) {
				scanf("%d", &cube[m][j]);
			}
		}

		cnt = 0; sign = 1;
		////若cnt不等於n表示n個物體未連成整體,dfs返回假表示不滿足第一個合法條件
		if (dfs(id) && cnt == n) {
			int ans = 1;
			for (int i = 0; i < 4; i++)
				ans *= (forw[i] - backw[i] + 1);
			//至於這裏why+1,可以想象如果前後都是0,那麼那至少也有1的量在這裏
			cout << ans << endl;
		}
		else cout << "Inconsistent" << endl;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章