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;
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值