正六面体染色
正六面体用4种颜色染色。
共有多少种不同的染色样式?
要考虑六面体可以任意旋转、翻转。
分析:六面体染色后任意旋转、翻转均判定为相同的染色方案,这点需要注意。
其实只有两种翻转方式,即水平翻转和竖直翻转。
创建一数组vis[333334],用于标记某方案是否已被访问。下标的每一个数位对应一个面的颜色编号。
因为是6个面,所以是个6数位;因为有四种颜色,所以每个数位为0~3的整数值
#include<iostream>
using namespace std;
#define f(a) for(a=0;a<4;a++)
bool vis[333334];
int sum;
//求某染色方案在vis的下标
int compute(int*);
//旋转正方体
void r(int,int,int,int,int,int);
int main() {
int a[6],t;
f(a[0])f(a[1])f(a[2])f(a[3])f(a[4])f(a[5]) {
t=compute(a); //求方案a对应vis的下标
if(vis[t]) continue;
sum++;
vis[t]=true;//标记方案t为已访问
//深搜,去除旋转后的重复方案
r(a[0],a[4],a[1],a[2],a[3],a[5]);
r(a[1],a[5],a[2],a[0],a[4],a[3]);
r(a[4],a[1],a[0],a[3],a[5],a[2]);
}
cout<<sum;
return 0;
}
//求染色方案a在vis的下标
int compute(int *a) {
return a[0]*100000+a[1]*10000+a[2]*1000+a[3]*100+a[4]*10+a[5];
}
//旋转正方体
void r(int a0,int a1,int a2,int a3,int a4,int a5) {
int a[6]= {a0,a1,a2,a3,a4,a5};
int t=compute(a);
if(vis[t]) return;
vis[t]=true;
//深搜
r(a[0],a[4],a[1],a[2],a[3],a[5]); //以“0”和“5”为轴旋转正方体
r(a[1],a[5],a[2],a[0],a[4],a[3]); //以“2”和“4”为轴旋转正方体
r(a[4],a[1],a[0],a[3],a[5],a[2]); //以“1”和“3”为轴旋转正方体
}
可直接用组合数学中的polya定理。
用n种颜色对正六面体进行染色的不同着色方案数为:
#include<stdio.h>
#include<math.h>
int main()
{
int n=4;
int sum=(pow(n,6)+3*pow(n,4)+12*pow(n,3)+8*pow(n,2))/24;
printf("%d",sum);
return 0;
}