zoukankan      html  css  js  c++  java
  • UVA1352

    题面

    题意

    告诉你若干立方体每个面的颜色,让你在所有立方体上重新染尽可能少的面以使得最终这些立方体完全一样,即对应面颜色均相同。(包括立方体以任意方向摆放时相同)

    解法

    如题意模拟,代码有一定难度。

    我们先使用dfs来枚举出每一个立方体摆放的方向,然后在确定完 (n) 个立方体的摆放方向后,对于每一个面,找到最优的颜色并且把所有立方体的该面都染成上述颜色,最后统计答案即可。

    这里我写了一个 near(i,j) 的函数来帮助我计算当立方体以 (i) 面向前, (j) 面向上时左面的编号。(在考场上我手造了一个小立方体搓了半天搓出来的)你也同样可以使用预处理方向矩阵的方式来代替这一操作。

    详情见代码。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    #define oppo(i) (5 - i)
    //oppo(i)即为立方体上i对面的面
    
    map<string, int> has;  //哈希
    
    int rec[5][8],  //记录每个立方体每个面的颜色
        vis[5][8];  //表示当前dfs状态下前后左右上下分别对应原立方体的哪个面
    int bucket[30];
    int n, answer;
    
    int near(int i, int j) {  //求出夹在i与j之间的面
        if (i == 1)
            if (j == 2)
                return 3;
            else if (j == 3)
                return 5;
            else if (j == 5)
                return 4;
            else
                return 2;
        else if (i == 2)
            if (j == 1)
                return 4;
            else if (j == 4)
                return 6;
            else if (j == 6)
                return 3;
            else
                return 1;
        else if (i == 3)
            if (j == 1)
                return 2;
            else if (j == 2)
                return 6;
            else if (j == 6)
                return 5;
            else
                return 1;
        else if (i == 4)
            if (j == 1)
                return 5;
            else if (j == 5)
                return 6;
            else if (j == 6)
                return 2;
            else
                return 1;
        else if (i == 5)
            if (j == 1)
                return 3;
            else if (j == 3)
                return 6;
            else if (j == 6)
                return 4;
            else
                return 1;
        else if (j == 2)
            return 4;
        else if (j == 4)
            return 5;
        else if (j == 5)
            return 3;
        else
            return 2;
    }
    
    void dfs(int depth) {
        if (depth == n) {  //如果n个立方体的方向都已确定
            int tot = 0;
            for (int i = 0; i < 6; i++) {
                memset(bucket, 0, sizeof(bucket));  //使用桶来记录所有该面出现过的颜色数量
                for (int j = 0; j < n; j++)
                    bucket[rec[j][vis[j][i]]]++;
                int ans = bucket[1];
                for (int j = 2; j < 30; j++)
                    ans = max(ans, bucket[j]);  //取出现次数最多的颜色数量
                tot += n - ans;                 //用总量减去该颜色数量即为最优解
            }
            answer = min(answer, tot);
            return;
        }
        for (int i = 0; i < 6; i++)  //枚举当前立方体的方向
            for (int j = 0; j < 6; j++)
                if (j != i && j != oppo(i)) {
                    int k = near(i + 1, j + 1) - 1;
                    vis[depth][0] = i, vis[depth][1] = j, vis[depth][2] = k,  //确定每一个面与原立方体的关系
                        vis[depth][3] = oppo(k), vis[depth][4] = oppo(j), vis[depth][5] = oppo(i);
                    dfs(depth + 1);
                }
    }
    
    int main() {
        ios::sync_with_stdio(false);
        while ((cin >> n) && n) {
            int cnt = 0;
            for (int i = 0; i < n; i++)
                for (int j = 0; j < 6; j++) {
                    string face;
                    cin >> face;
                    if (has.find(face) == has.end())  //hash
                        has[face] = ++cnt;
                    rec[i][j] = has[face];
                }
            answer = 0x3f3f3f3f;
            dfs(0);
            printf("%d
    ", answer);
            has.clear();
        }
        return 0;
    }
    
  • 相关阅读:
    单网卡ADSL共享上网的设置
    单网卡ADSL共享上网的设置
    求阶乘的函数
    用递归算法求两个数的最大公约数
    编程求组合
    汉诺塔游戏
    求两个数的最小公倍数
    快排的非递归算法
    字符串匹配之通配符问题一串首尾相连的珠子(m个),有N种颜色(N《=10),设计一个算法,取出其中一段,要求包含所有N中颜色,并使长度最短。
    sizeof和strlen
  • 原文地址:https://www.cnblogs.com/macesuted/p/solution-UVA1352.html
Copyright © 2011-2022 走看看