刘汝佳大神书上的题目,每一个方框有24中不同的姿态,第一个方块的姿态不变,然后去枚举后面的几个方块的姿态,最佳的涂色方案必然是各个方块处于一个固定的姿态然后进行涂色,在几个方块的姿态在枚举中都固定之后,当前这种姿态的排列方式中,最少的涂色方式应该是先统计几个方块的某个同一个面的颜色是什么,其中把颜色最多的一种颜色选为标准的颜色,把这几个方块的这个面都涂成这个颜色,那么对应的涂色次数自然就最小的,枚举所有姿态的组合,不停更新最小的涂色总次数就行了,书上说得不是很清楚,想了半天才想通原来书上说得是这个意思。
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <set>
#include <map>
#define INF 0x3fffffff
using namespace std;
string cube[4][6];
string cube_try[4][6];
set<string> all_colors;
int n, min_sum;
int format[24][6] = {
{0, 1, 2, 3, 4, 5},
{4, 0, 2, 3, 5, 1},
{5, 4, 2, 3, 1, 0},
{1, 5, 2, 3, 0, 4},
{3, 1, 0, 5, 4, 2},
{4, 3, 0, 5, 2, 1},
{2, 4, 0, 5, 1, 3},
{1, 2, 0, 5, 3, 4},
{0, 3, 1, 4, 2, 5},
{2, 0, 1, 4, 5, 3},
{5, 2, 1, 4, 3, 0},
{3, 5, 1, 4, 0, 2},
{0, 2, 4, 1, 3, 5},
{3, 0, 4, 1, 5, 2},
{5, 3, 4, 1, 2, 0},
{2, 5, 4, 1, 0, 3},
{0, 4, 3, 2, 1, 5},
{1, 0, 3, 2, 5, 4},
{5, 1, 3, 2, 4, 0},
{4, 5, 3, 2, 0, 1},
{1, 3, 5, 0, 2, 4},
{2, 1, 5, 0, 4, 3},
{4, 2, 5, 0, 3, 1},
{3, 4, 5, 0, 1, 2}
};
void change_cube(string *source, string* des, int format_index){
int i;
for(i=0; i<6; i++){
des[i] = source[format[format_index][i]];
}
}
void dfs(int cur){
int i, j, k, max, count;
string color;
map<string, int> m;
if(0 == cur){
for(i=0; i<6; i++) cube_try[0][i] = cube[0][i];
dfs(cur+1);
return;
}
else{
for(i=0; i<24;i++){
change_cube(cube[cur], cube_try[cur], i);
if(cur <= n-2)
dfs(cur+1);
else{
count = 0;
for(k=0; k<6; k++){
m.clear();
max = 0;
for(j=0; j<n; j++){
color = cube_try[j][k];
if(m.find(color) == m.end())
m[color] = 1;
else
m[color]++;
if(m[color] > max)
max = m[color];
}
count += n-max;
}
if(count < min_sum)
min_sum = count;
}
}
}
}
void func(int n){
if(1 == n){
printf("0\n");
return;
}
min_sum = INF;
dfs(0);
printf("%d\n", min_sum);
}
int main(void){
char buf[20];
string color;
int i, j;
//freopen("input.dat", "r", stdin);
all_colors.clear();
while(scanf("%d", &n), n){
for(i=0; i<n; i++){
for(j=0; j<6; j++){
scanf("%s", buf);
color.assign(buf);
cube[i][j] = color;
all_colors.insert(color);
}
}
func(n);
}
return 0;
}