題意:有n個帶顏色的立方體,每個立方體每個面都塗有一種顏色。要求重新塗儘量少的面,使得所有立方體完全相同。兩個立方體完全相同是指存在一種旋轉方式,使得這兩個立方體對應面顏色完全一樣。
很暴力的題。首先每個立方體經過旋轉,只有24種不同的狀態(先選一個面作爲前面,6種選法,然後選一個面作爲上面,4種選法。共6*4 = 24種)。而n最大隻有4,而且兩個立方體經過旋轉可以完全相同的話,我們可以一個立方體不動作爲參照。這樣只需要枚舉最多3個立方體的所有狀態,也就是最多24^3種狀態組合。然後每個狀態下比較所有立方體的每個面,對於每個面找出顏色相同的面的最大值,這些面都不重新塗,而重新塗剩下與他們不同顏色的面。這樣複雜度是O(24^(n - 1)*n*6)可以通過這個題。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
using namespace std;
//定義24種狀態的6個面編號,第二維0-5分別表示上、下、左、右、前、後面的編號
const int state[24][6] =
{
{1, 6, 2, 5, 3, 4}, {1, 6, 3, 4, 5, 2}, {1, 6, 5, 2, 4, 3}, {1, 6, 4, 3, 2, 5},
{6, 1, 2, 5, 4, 3}, {6, 1, 4, 3, 5, 2}, {6, 1, 5, 2, 3, 4}, {6, 1, 3, 4, 2, 5},
{2, 5, 6, 1, 3, 4}, {2, 5, 3, 4, 1, 6}, {2, 5, 1, 6, 4, 3}, {2, 5, 4, 3, 6, 1},
{5, 2, 1, 6, 3, 4}, {5, 2, 3, 4, 6, 1}, {5, 2, 6, 1, 4, 3}, {5, 2, 4, 3, 1, 6},
{3, 4, 2, 5, 6, 1}, {3, 4, 6, 1, 5, 2}, {3, 4, 5, 2, 1, 6}, {3, 4, 1, 6, 2, 5},
{4, 3, 2, 5, 1, 6}, {4, 3, 1, 6, 5, 2}, {4, 3, 5, 2, 6, 1}, {4, 3, 6, 1, 2, 5},
};
const int MAX = 30;
int n;
char cube[5][6][MAX];
map <string, int> ma[6];
void input()
{
for(int i = 0; i < n; i++)
{
for(int j = 0; j < 6; j++)
scanf("%s", cube[i][j]);
}
}
void solve()
{
int total = 1; //存儲一共的狀態組合
int ans = 24; //初始化最大值
for(int i = 1; i < n; i++) //i從1開始,第一個立方體不用旋轉,作爲參考系即可
total *= 24;
int cnt[6];
while(total--)
{
memset(cnt, 0, sizeof(cnt));
for(int i = 0; i < 6; i++)
ma[i].clear();
int temp = total;
for(int i = 0; i < n; i++)
{
int pos = temp%24; //24進製法求每個立方體的狀態
temp /= 24;
for(int j = 0; j < 6; j++)
cnt[j] = max(cnt[j], ++ma[j][cube[i][state[pos][j] - 1]]); // -1是因爲數組下標對應問題
}
int temp_ans = 0;
for(int i = 0; i < 6; i++)
temp_ans += n - cnt[i];
ans = min(ans, temp_ans);
}
printf("%d\n", ans);
}
int main()
{
while(scanf("%d", &n) && n != 0)
{
input();
solve();
}
return 0;
}