LA 3041 Colored Cubes (暴力枚举+贪心)
2016-12-08 19:54
459 查看
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; }
相关文章推荐
- 实验11——指针的基础应用
- roundcube
- 【C++学习】【阶段一】数据初始化&运算符优先级&条件循环语句
- VS2013/MFC编程入门之三十七(文档、视图和框架:各对象之间的关系)
- 剑指offer——面试题39:二叉树的深度
- 【Caffe】Ubuntu安装Protobuf2.5
- STM32学习2
- quartz (从原理到应用)详解篇
- 并查集找亲戚
- selenium 概念及练习 !
- Java的swing界面拖拽文件至文本框显示文件路径
- RecyclerView ItemTouchHelper
- 线代中最基础的两种玩法
- 关于Linux线程的线程栈以及TLS
- 工作一年感悟
- Android中的各种访问权限Permission含义
- 实验11——指针的基础应用
- 软件测试之功能测试
- k好数
- Android Studio 设置 SVN