题目大意:
对两个骰子染三种颜色,问我们是否可以通过对某个骰子进行旋转得到另一个骰子。
解题思路:
网上大多都是模拟暴力的过程,这里我给出另一种解决思路。其实骰子我们可以建为一个图。每一个面作为一个节点,每个节点之间的连接我们连一条边。现在问题等价于转换为求两个图的同构。同构是什么意思呢?我们可以对每个节点进行标号,我们找到两个图中的点的一一对应关系,之后我们证明按照这样一一对应后,这两个图的边连接情况也是一样的。具体如下图介绍。
这两个图看似不一样,但是我们把1和6映射; 4和9映射;2和8映射;3和7映射。我们发现经过这样一一对应后,比如1和4之间有一条边,经过映射6和9之间也有一条边,通过遍历边集,我们就能发现左边的图中的边在右面的图中也有(即边的重数要一样),我们认为这两个图同构。
在这里同样的,我们也是枚举这种点对应关系,但是这里不是判定边的重数,这里我们需要判定的是两点的颜色是否一致。
比如 1 - 4 对应颜色为 r - g,经过映射后为 5 - 6 那么它们的对应颜色也应该是 r- g.
#include <bits/stdc++.h>
using namespace std;
int main(){
pair<char,char> gra1[6][6];
pair<char,char> gra2[6][6];
for(int i=0;i<6;i++)
for(int j=0;j<6;j++)gra2[i][j]=make_pair('n','n');
int rule[7][4]={{0,0,0,0},{2,3,4,5},{1,4,6,3},\
{1,2,5,6},
{1,2,5,6} ,
{1,4,6,3},
{2,4,3,5}
};
string str;
while(cin>>str)
{
for(int i=0;i<6;i++)
for(int j=0;j<4;j++){
int u=i+1;
int nx=rule[i+1][j];
gra1[u-1][nx-1] =make_pair(str[u-1] ,str[nx-1]);
}
for(int i=0;i<6;i++)
for(int j=0;j<4;j++){
int u=i+1;
int nx=rule[i+1][j];
gra2[u-1][nx-1] =make_pair(str[6+u-1] ,str[6+nx-1]);
}
vector<int> per;
for(int i=0;i<=5;i++)per.push_back(i);
int finsuc=0;
do{
int suc=1;
for(int i=0;i<6;i++){
for(int j=0;j<4;j++){
int u=i+1;
int nx=rule[i+1][j];
int mapu=per[u-1];
int mapnx=per[nx-1];
char c1=gra1[u-1][nx-1].first;
char c2=gra1[u-1][nx-1].second;
char mapc1=gra2[mapu][mapnx].first;
char mapc2=gra2[mapu][mapnx].second;
if(mapc1 != c1 || mapc2 != c2){
suc=0;
}
}
}
if(suc){
finsuc=1;
cout<<"TRUE"<<endl;
break;
}
}while(next_permutation(per.begin(),per.end()));
if(!finsuc)cout<<"FALSE"<<endl;
}
}