算法竞赛入门经典训练指南打卡
题目链接:UVALive 3401
思路
题目的要求是让所有的立方体完全相同,其实就是让n个正方体变成一样的
对于一个正方体,可以让任意一个面作为前面,然后以一个和它相邻的面作为顶面
所以对于一个正方体,按照题目的编号方式,可以有24种情况(如果实在无法理解,可以用一个魔方,选一个颜色对着你,再选一个颜色朝着上方,你会发现有24种放法)
假设有两个正方体,一个正方体我们作为参照,另一个正方体用一种放法,两个立方体只有一个面的颜色不同,其他面颜色一致,则需要涂的面就只有一个面
我们只需要查找24种放法里面,哪一种放法需要涂改的面的数目最少,输出该数目即可
具体细节看代码注释
代码如下:
#include <iostream>
#include <cstring>
#include <vector>
#define ton(i , n) for(int i = 0 ; i < n ; ++ i)
int pose[24][6] = {{2, 1, 5, 0, 4, 3}, //24种放法
{2, 0, 1, 4, 5, 3},
{2, 4, 0, 5, 1, 3},
{2, 5, 4, 1, 0, 3},
{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, 4, 5, 0, 1, 2},
{3, 5, 1, 4, 0, 2},
{3, 1, 0, 5, 4, 2},
{3, 0, 4, 1, 5, 2}} ;
using namespace std ;
int n , ans , dice[4][6] ;
int r[4] , color[4][6] ;
string name ;
vector<string> names ; //存放立方体的颜色名,如如blue、res等等,索引作为颜色的数字编号
int Get_id(){
int len = names.size() ;
ton(i , len)
if(names[i] == name)
return i ; //如果该颜色之前已经存了的,则直接返回该颜色对应的数字编号
names.push_back(name) ; //如果names数组中没有改颜色,则放入数组中,并且返回它的索引
return len ;
}
void check(){
ton(i , n)
ton(j , 6)
color[i][pose[r[i]][j]] = dice[i][j] ; //获取旋转到该姿态之后,还没涂改颜色的时候每个面对应颜色
int tot = 0 ; //记录需要涂改颜色的面的个数
ton(j , 6){ //每个面进行比较
int cnt[4 * 6] ; //每种颜色出现的次数
memset(cnt , 0 , sizeof(cnt)) ;
int maxface = 0 ;
ton(i , n)
maxface = max(maxface , ++cnt[color[i][j]]) ; //第i个立方体第j个面的颜色出现次数+1
tot += n - maxface ; //对于第j个面,maxface存放的是出现次数最多的颜色出现的次数,所以将不是该颜色的面涂成该颜色
}
ans = min(ans , tot) ;
}
void dfs(int d){
if(d == n)
check() ; //找到最后一个立方体了
else{
ton(i , 24){
r[d] = i ;
dfs(d + 1) ; //继续找下一个立方体
}
}
}
int main(){
while(cin >> n && n){
names.clear() ; //清除记录颜色的数组
ton(i , n)
ton(j , 6){
cin >> name ; //输入颜色
dice[i][j] = Get_id() ; //将颜色名转换为数字
}
ans = 6 * n ; //ans为需要涂的面的个数,6 * n显然是不可能达到的,便于我们后面更新ans
r[0] = 0 ; //第一个正方形不旋转,作为参考
dfs(1) ;
cout << ans << endl ;
}
return 0 ;
}