题意:给出n个立方体,(n<=4),每个面上均有颜色,问最少重新涂多少个面的颜色使得所有立方体相同。
解法:暴力枚举,难在编写程序。
一个立方体有24个姿势,因为上面有6中可能,难后前面又有4中可能,故有24种可能。
现在让第一个立方体任选一种姿势,然后枚举其他立方体的姿势,然后在姿势不变的情况下涂色,求最少涂色数。
对于每一个面,找出n个立方体中最多的颜色color,它的数量为cnt[color],然后所有立方体的这个面共需要重涂n-cnt[color] 次。
0 正面
1 右
2 上
3 下
4 左
5 反面
主代码:
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const int maxn=4 ;
map<string ,int >mp;
char s[30];
int cube24[24][6]={
{2,1,5,0,4,3},{2,0,1,4,5,3},{2,4,0,5,1,3},{2,5,4,1,0,3},
//第一行表示,编号为0的面现在都在原来编号为2的面的位置。
{4,2,5,0,3,1},{5,2,1,4,3,0},{1,2,0,5,3,4},{0,2,4,1,3,5},
{0,1,2,3,4,5},{4,0,2,3,5,1},{5,4,2,3,1,0},{1,5,2,3,0,4},
{5,1,3,2,4,0},{1,0,3,2,5,4},{0,4,3,2,1,5},{4,5,3,2,0,1},
{1,3,5,0,2,4},{0,3,1,4,2,5},{4,3,0,5,2,1},{5,3,4,1,2,0},
{3,1,0,5,4,2},{3,0,4,1,5,2},{3,4,5,0,1,2},{3,5,1,4,0,2}
};
int n,ans,N,r[maxn+3],color[maxn+3][maxn+3],cube[maxn+3][maxn+3];
int ID(char* s)
{
string ss(s);
if(mp.count(s))
{
return mp[s];
}
mp[s]=N++;
return mp[s];
}
int cnt[4*24+5];
void check()
{
for0(i,n)
{
for0(j,6)
{
color[i][cube24[r[i]][j]] =cube[i][j] ;
}
}
int tot=0;
for(int j=0;j<6;j++)//枚举面
{
int maxi=0;
memset(cnt,0,sizeof cnt);
for(int i=0;i<n;i++)
{
maxi=max(maxi,++cnt[ color[i][j] ] );
}
tot+= n-maxi;
}
ans=min(ans,tot);
}
void dfs(int x)
{
if(x==n)
{
check();
return;
}
for(int j=0;j<24;j++)
{
r[x]=j;
dfs(x+1);
}
}
int main()
{
while(~scanf("%d",&n)&&n)
{
N=0;mp.clear();
for0(i,n)
{
for0(j,6)
{
scanf("%s",s);
cube[i][j]=ID(s);
}
}
ans=INF;
r[0]=0;//第一个立方体用哪种摆放方式随意
dfs(1);
printf("%d\n",ans);
}
return 0;
}
/**
时间复杂度O(24^(n-1) *n*6)
**/
打表:
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
int L[6]={ 4,0,2,3,5,1 };
int U[6]={ 2,1,5,0,4,3 };//原来是0,现在向上翻转了,到了位置2
void rot(int *p)//p[0]表示编号为0的立方体现在在何处。
{
int q[6];
memcpy(q,p,sizeof q);
for0(i,6)
{
p[i]= L[ q[i] ] ;//某颜色的新位置=原位置经过L()映射
}
}
void up(int *p)
{
int q[6];
memcpy(q,p,sizeof q);//这里必须写 memcpy(q,p,sizeof q);不能写sizeof p,因为p是指针
for0(i,6)
{
p[i]= U[ q[i] ] ;
}
}
void out(int *p)
{
printf("{");
for0(i,6)
{
if(i) printf(",");
printf("%d",p[i]);
}
printf("}");
}
int main()
{
int p0[]={0,1,2,3,4,5};
printf("int cube24[24][6]={\n");
for(int i=0;i<6;i++ )
{
int p[6];
memcpy(p,p0,sizeof p0);
if(i==0) { up(p); }
else if(i==1) { rot(p);up(p); }
else if(i==2) { }
else if(i==3) { up(p);up(p); }
else if(i==4){ rot(p); rot(p);rot(p);up(p); }
else if(i==5){ up(p);up(p);up(p); }
for0(j,4)
{
if(i||j) printf(",");
out(p);
rot(p);
}
}
printf("\n};\n");
return 0;
}