题目链接:
点击打开链接
题目大意:
给出一个二阶魔方,判断这个魔方是否是能够还原的
题目分析:
首先我们去想一个被还原的魔方,那么这个魔方的相对的面的颜色是一定的,我们给魔方的每一个小面一个权值,那么我们选取黄面(随机选取的),那么与它相对的是白面,对于黄面上的四个点,他们的权值都是0,因为每个小面都是可以通过固定没有重复的旋转方向的次数回到它本身所在的面或它所对的面,也就是3次,那么每次旋转它,就有一个-1,或者1,用来标记到下一状态的距离,和回到当前状态的距离。
初始情况下,到下一状态的距离是3,到自身状态的距离是0。所以黄白面所在的小面的权值之和能被3正除
那么如果我们旋转了一次,会导致两个黄面和两个白面动,然而不会导致权值之和与3的倍数关系
因为两个连续的颜色格,一个相当于到达奇数位状态远离了一步,到达偶数位的状态增加了一步,另一个相反,因为相邻,所以他们两个的奇偶性一定不同,所以说最终的权值之和与3的倍数关系不变。
因为每个面到达奇数位和偶数位的距离之和一定是3,而且奇数位和偶数位的数量是一定的,所以如果一个到达偶数位的距离为2,那么一定存在一个到达偶数位距离为1的面,才能维护这种关系。
盲拧和色向能够保住理解,可以去魔方的兴趣爱好者那里了解一下。
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <vector> using namespace std; char s[10]; int t; int wh[] = {7,8,13,14,21,22,23,24}; int add[] = {1,4,6,10,11,15,17,20}; int main ( ) { int c = 1; scanf ( "%d" , &t ); while ( t-- ) { int ans = 0; for ( int i = 1 ; i <= 24 ; i++ ) { scanf ( "%s" , s ); if ( s[0] == 'w' || s[0] == 'y' ) { bool flag = true; for ( int j = 0 ; j < 8 ; j++ ) if ( wh[j] == i ) { flag = false; break; } else if ( add[j] == i ) { ans++; flag = false; break; } if ( flag ) ans--; } } //cout << "YES : " << ans << endl; printf ( "Case #%d: " , c++ ); if ( ans%3 == 0 ) puts ("YES"); else puts ("NO"); } }