UVAL colored cubes 打表 暴力枚举
来源:互联网 发布:bluetooth网络连接 编辑:程序博客网 时间:2024/06/05 01:03
题意:有n个带颜色的立方体,每个面涂有一种颜色。要求重新涂尽量少的面,使得所有立方体完全相同。两个立方体完全相同的含义是:存在一种旋转方式,使得两个立方体对应面的颜色完全相同。
思路:因为立方体的个数比较少,我们可以暴力解决。
首先,我们要求立方体的旋转方式。可以计算得到,有24种旋转方式。但是,如果手动求出这些方式,会很麻烦的,也很容易犯错。
每种选择对对应一种全排列P。其中,p[i]表示编号i所在的位置(1表示正面,2表示右面,3表示上面,4表示下面,5表示左面,6表示后面)。标准状态为1,2,3,4,5,6;
对于标准状态向左旋转,对应的排列为:5,1,3,4,6,2,向上旋转为:3,2,6,1,5,4。
对于这两个操作,我们可以把它们看做基本操作,其他状态可以看做是这些基本操作组合得到的:
1.1在顶面的状态:向上翻一次,再左转0-3次。
2.2在顶面的状态,向左转一次,在左转0-3次。
3.3在顶面的状态: 直接左转0-3次。
4.4在顶面的状态:向上翻转2次,再向左转0-3次。
5.5在顶面的姿态:向左转3次,向上翻一次,再向左转0-3次、
6.6在顶面的状态,向左转2次,再向上翻一次,再向左转0-3次。
生成24中旋转的代码如下:
#include<cstdio>#include<cstring>using namespace std;int left[] = {4, 0, 2, 3, 5, 1};int up[] = {2, 1, 5, 0, 4, 3};// 按照排列T旋转姿态pvoid rot(int* T, int* p) { int q[6]; memcpy(q, p, sizeof(q)); for(int i = 0; i < 6; i++) p[i] = T[q[i]];}void enumerate_permutations() { int p0[6] = {0, 1, 2, 3, 4, 5}; printf("int dice24[24][6] = {\n"); for(int i = 0; i < 6; i++) { int p[6]; memcpy(p, p0, sizeof(p0)); if(i == 0) rot(up, p); if(i == 1) { rot(left, p); rot(up, p); } if(i == 3) { rot(up, p); rot(up, p); } if(i == 4) { rot(left, p); rot(left, p); rot(left, p); rot(up, p); } if(i == 5) { rot(left, p); rot(left, p); rot(up, p); } for(int j = 0; j < 4; j++) { printf("{%d, %d, %d, %d, %d, %d},\n", p[0], p[1], p[2], p[3], p[4], p[5]); rot(left, p); } } printf("};\n");}int main() { enumerate_permutations(); return 0;}
这样,我们就得到了24种旋转方式。
但是如何再暴力的做呢?如果只是简单的枚举每个面的颜色,然旋转,判断是否相同,复杂度为24 ^ 6,不可行。
如果以第一个正方体为标准,枚举其他三个正方体旋转的状态。然后,对于每个面,选出出现次数最多的颜色,将其他不同的颜色重涂为该颜色。这样,复杂度为24^3.
代码如下:
int dice24[24][6] = {{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},{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},};#include<cstdio>#include<cstring>#include<string>#include<vector>#include<algorithm>using namespace std;const int maxn = 4;int n, dice[maxn][6], ans;vector<string> names;int ID(const char* name) { string s(name); int n = names.size(); for(int i = 0; i < n; i++) if(names[i] == s) return i; names.push_back(s); return n;}int r[maxn], color[maxn][6]; // 每个立方体的旋转方式和旋转后各个面的颜色void check() { for(int i = 0; i < n; i++) for(int j = 0; j < 6; j++) color[i][dice24[r[i]][j]] = dice[i][j]; int tot = 0; // 需要重新涂色的面数 for(int j = 0; j < 6; j++) { // 考虑每个面 int cnt[maxn*6]; // 每种颜色出现的次数 memset(cnt, 0, sizeof(cnt)); int maxface = 0; for(int i = 0; i < n; i++) maxface = max(maxface, ++cnt[color[i][j]]); tot += n - maxface; } ans = min(ans, tot);}void dfs(int d) { if(d == n) check(); else for(int i = 0; i < 24; i++) { r[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); dice[i][j] = ID(name);//颜色散列 } ans = n*6; // 上界:所有面都重涂色 r[0] = 0; // 第一个立方体不旋转 dfs(1); printf("%d\n", ans); } return 0;}
- UVAL colored cubes 打表 暴力枚举
- uva1352 - Colored Cubes 打表+暴力
- UVA 1352 Colored Cubes(暴力搜索枚举)
- LA 3041 Colored Cubes (暴力枚举+贪心)
- uvaLive 3401 Colored Cubes 暴力
- LA 3401 Colored Cubes 暴力 -
- 1352 - Colored Cubes (枚举方法)
- UVALive - 3401 Colored Cubes 枚举
- uva 1352 - Colored Cubes(枚举)
- Poj 2741Colored Cubes(贪心&枚举)
- uva 1352 Colored Cubes(枚举)
- uva 1352 - Colored Cubes(枚举)
- Colored Cubes
- Colored Cubes
- Colored Cubes
- Perfect Cubes[打表]
- Tokyo 2005 / UVa 1352 Colored Cubes (部分枚举&贪心)
- Uva 1352 Colored Cubes 解题报告(枚举+码力)
- 花生壳解析错误解决方法
- HDU 5006 Resistance(鞍山网络赛J题)
- (process:6471): GConf-WARNING **: 等类似错误
- ITK 从安装-----测试心得 在win7 64位机
- 闰年判断方法二
- UVAL colored cubes 打表 暴力枚举
- tessetset
- 一个图论中的概念:Betweenness Centrality
- jbpm4 回退、会签、撤销、自由流
- Java的目录树的创建与展示
- Cocos2d-x学习笔记(五)-------->CCSprite精灵
- 数据库触发器
- JBPM WEB CONSOLE安装实录
- 【VC++类型转换】string转换为CString