Bootstrap

UVA 1352 Colored Cubes(回溯)

题目大意:

给出n个正方体,然后n行表示每个正方体6个面的上色,问涂最少的面使得n正方体都相同(注意正方体是可以旋转的)。

解析:

首先写出正方体有24个旋转方式,然后以第一个正方体为标准,枚举剩下n - 1个正方体的状态,然后计算最小值。具体见代码注释。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <map>
using namespace std;
const int dice24[24][6] = {  //24种旋转方法  
    {2, 1, 5, 0, 4, 3}, {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},  
};
const int MAX = 4;
int n, dice[MAX][6] ,ans;
int cnt;
int r[MAX], color[MAX][6];
map<string,int> names;
int id(char name[]) {
    string s(name);
    if(names.count(s)) {
        return names[s];
    }
    names[s] = cnt++;
    return names[s];
}
void check() {
    //保存旋转的颜色
    for(int i = 0; i < n; i++) { //枚举所有保存的旋转
        for(int j = 0; j < 6; j++) { //枚举旋转的面
            color[i][dice24[r[i]][j]] = dice[i][j];
        }
    }
    int tot = 0;
    int cnt[MAX*6];
    for(int j = 0; j < 6; j++) {
        int Max = 0;
        memset(cnt,0,sizeof(cnt));
        for(int i = 0; i < n; i++) {
            cnt[color[i][j]]++;
            Max = max(Max,cnt[color[i][j]]);
        }
        tot += (n - Max);
    }
    ans = min(ans, tot);
}
void dfs(int cur) {
    if(cur == n) {
        check();
        return ;
    }
    for(int i = 0; i < 24; i++) { //枚举24种状态
        r[cur] = i;
        dfs(cur+1);
    }
}
int main() {
    char name[30];
    while(scanf("%d",&n) != EOF && n) {
        names.clear();
        cnt = 0;
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < 6; j++) {
                scanf("%s",name);
                dice[i][j] = id(name);
            }
        }
        ans = n*6; //上界:所有的面都有颜色
        r[0] = 0; //第一个立方体不旋转
        dfs(1);
        printf("%d\n",ans);
    }
    return 0;
}
;