LA 3041 Colored Cubes (暴力枚举+贪心)

来源:互联网 发布:口红与经济数据表格 编辑:程序博客网 时间:2024/05/18 17:27

LA 3041 Colored Cubes

题目大意:

给n个立方体,每面涂有一颜色,如何尽可能少的涂色,使得所有立方体完全相同.两个立方体相同指存在一种旋转方式使得两个立方体完全一致.

题目分析:

n<=4,比较小,所以可以想到以某一个立方体为标准,不旋转这个标准立方体,枚举其他立方体旋转情况,使得在某一情况下的花费最少.
当然问题就在于如何枚举出某一立方体的所有旋转形态,以每一个面为正面,存在4种形态,共计6*4=24种形态.这个计算形态个数的方法实际上也提供了一种可行思路:先枚举某一个面是那个面,再旋转0~3次统计形态个数,制成常量表以供使用.

maker制表代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int up[]={2,1,5,0,4,3};//向上翻const int left[]={4,0,2,3,5,1};//向左翻void rot(const int* T,int* p)//p序列按照T方式翻转{    int q[10];    for(int i=0;i<6;i++) q[i]=p[i];    for(int i=0;i<6;i++) p[i]=T[q[i]];}void init()//制表{    int p0[]={0,1,2,3,4,5};    printf("const int poses[24][6]={\n");    for(int i=0;i<6;i++) {        int p[10];        for(int j=0;j<6;j++) p[j]=p0[j];        switch(i) {//不同面朝上的处理            case 0:rot(up,p);break;            case 1:rot(left,p);rot(up,p);break;            case 3:rot(up,p);rot(up,p);break;            case 4:rot(left,p);rot(left,p);rot(left,p);rot(up,p);break;            case 5:rot(left,p);rot(left,p);rot(up,p);break;        }        for(int j=0;j<4;j++)            printf("{%d,%d,%d,%d,%d,%d},",p[0],p[1],p[2],p[3],p[4],p[5]),rot(left,p);        printf("\n");    }    printf("};");}int main(){    init();    return 0;}

代码:

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<vector>using namespace std;const int maxn=4;const int poses[24][6]={//maker制表代码制好的常量表     {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},    {3,4,5,0,1,2},{3,5,1,4,0,2},{3,1,0,5,4,2},{3,0,4,1,5,2},    {1,3,5,0,2,4},{0,3,1,4,2,5},{4,3,0,5,2,1},{5,3,4,1,2,0},    {5,1,3,2,4,0},{1,0,3,2,5,4},{0,4,3,2,1,5},{4,5,3,2,0,1},};vector<string>names;int ID(const char* name)//将颜色转换成数字编号 {    string s(name);    int d=names.size();    for(int i=0;i<d;i++)        if(s==names[i]) return i;    names.push_back(s);    return d;}int pre[maxn][6],n;//pre记录一开始的颜色分布 int rot[maxn],color[maxn][6],ans;//rot记录每个数组旋转情况,color记录旋转后的颜色分布 void check(){    for(int i=0;i<n;i++)        for(int j=0;j<6;j++)            color[i][poses[rot[i]][j]]=pre[i][j];    int tot=0;    for(int i=0;i<6;i++) {        int cnt[maxn*6];//统计各种颜色出现的次数,选择次数最多的那种颜色作为标准         memset(cnt,0,sizeof(cnt));        int maxs=0;        for(int j=0;j<n;j++) maxs=max(maxs,++cnt[color[j][i]]);        tot+=n-maxs;//需要涂色的面就是总个数-最多的颜色的面个数     }    ans=min(ans,tot);}void dfs(int d)//dfs枚举旋转情况 {    if(d==n) check();    else for(int i=0;i<24;i++) rot[d]=i,dfs(d+1);}int main(){    while(scanf("%d",&n)==1&&n) {        names.clear();        for(int i=0;i<n;i++) for(int j=0;j<6;j++) {            char name[30];            scanf("%s",name);            pre[i][j]=ID(name);        }        ans=n*6;        rot[0]=0;//0号立方体不旋转         dfs(1);        printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击