hdu.oj 绝对不模拟的简单魔方

题目链接:

Problem - 7447 (hdu.edu.cn)

Problem Description

小T最近有些疲惫,想找一些能够放松自己的事情去做,正好想起上次被队友用三阶魔方暴杀的经历,就想苦练一下魔方技术,好在下次的对战中击败他的队友。

于是他在网上下单了一个魔方,让小C帮他去取快递。

可是小C有些调皮,私自拆开了快递,随意的扭了这个魔方**不超过三次**(扭的是侧面,不是中间层,且扭的角度固定为90度),还弄掉了**同一个角上的两片贴纸**。

小C的记性不太好,不太记得两片贴纸正确的位置了,所以随意的将两片贴纸贴了回去,并将这件事告诉了小T。

但小T作为一个还在学习如何还原底层十字的小萌新,面对被小C打乱过的魔方很是束手无策。

所以他向你寻求帮助,希望你告诉他小C有没有将两片贴纸正确的贴回去,如果没有的话,是哪一个角的贴纸贴错了呢。

Input

第一行有一个整数,T (1≤T≤10) ,代表数组组数

每组数据输入一个 9 行 12 列的字符型矩阵。
矩阵表示魔方的平面展开图,展开图的格式固定。

输入格式为:

表示一个魔方的平面展开图。

未打乱的魔方为:


"x"在输入的数据中是 [1,6] 中的一个数字,表示这个块原来属于哪一面。

保证所给的魔方至多被扭过三次,且只扭了侧面,没有旋转过中间层。

Output

如果两片贴纸被正确的贴了回去,输出"No problem",否则按升序输出贴错贴纸的角上的三个数字。

Sample Input

2 
***111****** 
***111****** 
***111****** 
223233444555 
222333444555 
222333444555 
***666****** 
***666****** 
***666****** 
***111****** 
***111****** 
***111****** 
333444555222 
222333444555 
222333444555 
***666****** 
***666****** 
***666******

Sample Output

1 2 3

No problem

来源

2024“钉耙编程”中国大学生算法设计超级联赛(2)

题目思路

题目要求撕了角块的两张贴纸看是否能还原成原魔方,告诉我们只需要看角块,也就是可以将魔方看为二阶魔方

题目的数据量不大所以可以用暴力枚举,我们只需要列出原魔方的复原形态,再将需要观察的魔方能够得到的各种形态对比,如果能找到一样的形态就输出“No problem”,如果找到和原魔方只差两片的,也只需要将那一块的三个颜色升序输出即可

推导过程

以第一组样例为例子

输入:

***111****** 
***111****** 
***111****** 
223233444555 
222333444555 
222333444555 
***666****** 
***666****** 
***666****** 

输出:

1 2 3(也就是第四行的3和4位置有误)

我们以中心块知道原排列有

如下:

1 3 2        1 4 3        1 5 4        1 2 5

6 2 3        6 3 4        6 4 5        6 5 2

可知1 2 3并不在这些数组里,无论标程中的第三个for如何组合都不会有1 2 3的组合所以直接输出

(如果不够清晰的话可以用以下样例测试:

***111****** 
***111****** 
***111****** 
222333444555 
222333444555 
222333444655 
***666****** 
***666****** 
***665****** 
遍历的多点更容易理解)

#include<bits/stdc++.h>
using namespace std;
string st[10];
bool vis[1005];//标记出现过的组合 
int x[6]= {0,3,3,3,3,6};//与其他数组组合产生x坐标 
int y[6]= {3,0,3,6,9,3};//与其他数组组合产生y坐标 
int a[8]= {0,0,0,0,5,5,5,5};//与其他数组组合产生每个组合中的第一个颜色 
int b[8]= {2,3,4,1,1,2,3,4};//与其他数组组合产生每个组合中的第二个颜色 
int c[8]= {1,2,3,4,2,3,4,1};//与其他数组组合产生每个组合中的第三个颜色

int dira[8][2]={2,0,2,2,0,2,0,0,0,0,0,2,2,2,2,0};
int dirb[8][2]={0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2};
int dirc[8][2]={0,2,0,2,0,2,0,2,2,0,2,0,2,0,2,0};
signed main() {
	int T;
	cin>>T;
	while(T--) {
		memset(vis,0,sizeof vis);
		for(int i=0; i<9; i++)cin>>st[i];
		for(int i=0; i<8; i++) {
			/*查询当前魔方的形态,思路中提到我们要将魔方看为二阶魔方也就是看它的八个角块
			当前的for就是要看我们原来魔方八个角块是什么形态,些角块是对应的
			这些可以从每个面的中心块看出来也就是以下代码*/
			int A=st[x[a[i]]+1][y[a[i]]+1]-'0';
			int B=st[x[b[i]]+1][y[b[i]]+1]-'0';
			int C=st[x[c[i]]+1][y[c[i]]+1]-'0';
			vis[A*100+B*10+C]=1;
			vis[B*100+C*10+A]=1;
			vis[C*100+A*10+B]=1;
		}
		/*
		原来魔方能得到的角块形态如下也就是跑for出来的结果
		vis
		1 3 2
		1 4 3
		1 5 4
		1 2 5
		6 2 3
		6 3 4
		6 4 5
		6 5 2
		接下来我们只需要找到上面vis数组中没有出现过的组合就行了 */
		int flag=1;
		for(int i=0; i<8; i++) {
			int A=st[x[a[i]]+dira[i][0]][y[a[i]]+dira[i][1]]-'0';
			int B=st[x[b[i]]+dirb[i][0]][y[b[i]]+dirb[i][1]]-'0';
			int C=st[x[c[i]]+dirc[i][0]][y[c[i]]+dirc[i][1]]-'0';
			if(vis[A*100+B*10+C])continue;
			flag=0;
			int tmp[3]= {A,B,C};
			sort(tmp,tmp+3);
			cout<<tmp[0]<<" "<<tmp[1]<<" "<<tmp[2]<<endl;
			break;
		}
		if(flag)cout<<"No problem"<<endl;
	}
	return 0;
}

欢迎讨论

  • 14
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值