UVALive 3401打卡

算法竞赛入门经典训练指南打卡

题目链接: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 ;
}

猜你喜欢

转载自blog.csdn.net/just_gong/article/details/107912164