uva1352 - Colored Cubes 打表+暴力

There are several colored cubes. All of them are of the same size but they may be colored differently. Each face of these cubes has a single color. Colors of distinct faces of a cube may or may not be the same.

Two cubes are said to be identically colored if some suitable rotations of one of the cubes give identical looks to both of the cubes. For example, two cubes shown in Figure 2 are identically colored. A set of cubes is said to be identically colored if every pair of them are identically colored.

A cube and its mirror image are not necessarily identically colored. For example, two cubes shown in Figure 3 are not identically colored.

You can make a given set of cubes identically colored by repainting some of the faces, whatever colors the faces may have. In Figure 4, repainting four faces makes the three cubes identically colored and repainting fewer faces will never do.

Your task is to write a program to calculate the minimum number of faces that needs to be repainted for a given set of cubes to become identically colored.

Input 

The input is a sequence of datasets. A dataset consists of a header and a body appearing in this order. A header is a line containing one positive integer n and the body following it consists of n lines. You can assume that 1$ \le$n$ \le$4 . Each line in a body contains six color names separated by a space. A color name consists of a word or words connected with a hyphen (-). A word consists of one or more lowercase letters. You can assume that a color name is at most 24-characters long including hyphens.

A dataset corresponds to a set of colored cubes. The integer n corresponds to the number of cubes. Each line of the body corresponds to a cube and describes the colors of its faces. Color names in a line is ordered in accordance with the numbering of faces shown in Figure 5. A line


color1 color2 color3 color4 color5 color6


corresponds to a cube colored as shown in Figure 6.

The end of the input is indicated by a line containing a single zero. It is not a dataset nor a part of a dataset.

\epsfbox{p3401a.eps}
Figure 2: Identically colored cubes
\epsfbox{p3401b.eps}
Figure 3: cubes that are not identically colored
\epsfbox{p3401c.eps}
Figure 4: An example of recoloring
\epsfbox{p3401d.eps}
Figure 5: Numbering of faces Figure 6: Coloring

Output 

For each dataset, output a line containing the minimum number of faces that need to be repainted to make the set of cub es identically colored.

Sample Input 

3 
scarlet green blue yellow magenta cyan 
blue pink green magenta cyan lemon 
purple red blue yellow cyan green 
2 
red green blue yellow magenta cyan 
cyan green blue yellow magenta red 
2 
red green gray gray magenta cyan 
cyan green gray gray magenta red 
2 
red green blue yellow magenta cyan 
magenta red blue yellow cyan green 
3 
red green blue yellow magenta cyan 
cyan green blue yellow magenta red 
magenta red blue yellow cyan green 
3 
blue green green green green blue 
green blue blue green green green 
green green green green green sea-green 
3 
red yellow red yellow red yellow 
red red yellow yellow red yellow 
red red red red red red 
4 
violet violet salmon salmon salmon salmon 
violet salmon salmon salmon salmon violet 
violet violet salmon salmon violet violet 
violet violet violet violet salmon salmon 
1 
red green blue yellow magenta cyan 
4 
magenta pink red scarlet vermilion wine-red 
aquamarine blue cyan indigo sky-blue turquoise-blue 
blond cream chrome-yellow lemon olive yellow 
chrome-green emerald-green green olive vilidian sky-blue 
0

Sample Output 

4 
2 
0 
0 
2 
3 
4 
4 
0 
16

  有N个方块,每个方块每个面有颜色,问最少改变多少个面的颜色,才能让这些方块全部一样(六个面没有区分,可以旋转)。

  如果枚举最终方块,4个方块最多24种颜色,有6个面,那就要枚举24^6次,太多了(有些状态是重复的,和另一些状态旋转方块得到的是一样的)。

  那么我们可以直接枚举每个方块的形态。以第一个方块为原始状态参照,枚举后面的方块的所有形态(第一个形态不用改变,因为如果改变,后面的方块也存在相应的形态对照,和原始状态重复)。分别以1,2,3,4,5,6为顶,每个顶有四个方向旋转,一共24种状态。如果N=4只需要枚举3个方块,这样最多就枚举24^3次了。

  24个形态可以手写。。但是又麻烦又容易出错。有个很好的方法,只用写出左转和上转这两个,就可以组合成所有状态!根据这个打表就比较简单了。

  打完状态表用DFS暴力搜索,出现的颜色用map映射最方便。

  我用的对应关系是旋转后第i个位置的变成了旋转前第j的位置的,当然也可以用旋转前第i个位置变到了旋转后的第j个位置这样的对应关系。


打表代码,不知道为什么输入逗号到文件出现汉字乱码。。

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#define INF 0x3f3f3f3f
#define MAXN 20
#define MAXM 20010
#define eps 1e-9
#define pii pair<int,int>
using namespace std;
int Left[10]={1,5,2,3,0,4};
int up[]={3,1,0,5,4,2};
void rot(int *T,int *p){
    int q[10];
    memcpy(q,p,sizeof(q));
    for(int i=0;i<6;i++) p[i]=q[T[i]];
}
int main(){
   // freopen("out.txt","w",stdout);
    int p0[]={0,1,2,3,4,5},p[10];
    for(int i=1;i<=6;i++){
        memcpy(p,p0,sizeof(p0));
        if(i==1) rot(up,p);
        if(i==2){
            rot(Left,p);
            rot(up,p);
        }
        if(i==4){
            rot(up,p);
            rot(up,p);
        }
        if(i==5){
            rot(Left,p);
            rot(Left,p);
            rot(Left,p);
            rot(up,p);
        }
        if(i==6){
            rot(up,p);
            rot(up,p);
            rot(up,p);
        }
        cout<<"{";
        for(int j=0;j<5;j++) cout<<p[j]<<",";
        cout<<p[5]<<"},";
        for(int k=0;k<3;k++){
            rot(Left,p);
            cout<<"{";
            for(int j=0;j<5;j++) cout<<p[j]<<",";
            cout<<p[5]<<"},";
        }
    }
    return 0;
}

AC代码

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#define INF 0x3f3f3f3f;
#define MAXN 110
using namespace std;
int rot[24][6]={{3,1,0,5,4,2},{1,2,0,5,3,4},{2,4,0,5,1,3},{4,3,0,5,2,1},{3,5,1,4,0,2},{5,2,1,4,3
,0},{2,0,1,4,5,3},{0,3,1,4,2,5},{0,1,2,3,4,5},{1,5,2,3,0,4},{5,4,2,3,1,0},{4,0,2
,3,5,1},{5,1,3,2,4,0},{1,0,3,2,5,4},{0,4,3,2,1,5},{4,5,3,2,0,1},{3,0,4,1,5,2},{0
,2,4,1,3,5},{2,5,4,1,0,3},{5,3,4,1,2,0},{2,1,5,0,4,3},{1,3,5,0,2,4},{3,4,5,0,1,2
},{4,2,5,0,3,1}};
int dice[MAXN][6],r[6],vis[30];
int N,M,ans;
map<string,int> Map;
void check(){
    int cnt=0;
    for(int i=0;i<6;i++){
        memset(vis,0,sizeof(vis));
        for(int j=0;j<N;j++) vis[dice[j][rot[r[j]][i]]]++;
        int MAX=0;
        for(int j=1;j<=M;j++) MAX=max(MAX,vis[j]);
        cnt+=N-MAX;
    }
    ans=min(ans,cnt);
}
void DFS(int cur){
    if(cur==N){
        check();
        return;
    }
    for(int i=0;i<24;i++){
        r[cur]=i;
        DFS(cur+1);
    }
}
int main(){
    freopen("in.txt","r",stdin);
    while(scanf("%d",&N),N){
        M=0;
        ans=INF;
        Map.clear();
        for(int i=0;i<N;i++)
            for(int j=0;j<6;j++){
                char name[30];
                scanf("%s",name);
                if(!Map[name]) Map[name]=++M;
                dice[i][j]=Map[name];
            }
        r[0]=8;
        DFS(1);
        printf("%d\n",ans);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值