poj 2741 Colored Cubes(dfs暴力枚举)
十分好的一个暴力枚举题,题意是,给出最多4个筛子,每个面都有一个颜色标记,要求求出最少改变多少个面,使得这些筛子可以通过某些旋转使其完全相同。
刚接到这题的时候,有点老鼠拉龟的感觉,首先想到的居然是dp。。。然后细心一想,这个题最多才4个筛子,何不直接暴力枚举呢?枚举复杂度最多才到O(24^n),因为筛子一共有24种放置的方法。然后一个问题就来了,这24种状态要怎么搞出来?一个不小心错了一个数字就很难debug 的了。于是,我在草稿纸上写了前面是1的4种情况,然后发现其余的,前面是2~6的各自的4种情况都是一样的转换方式,所以之后的直接利用转换即刻得到,具体查看代码。
最后套上一个dfs就大功告成了!
View Code
1 const int base[6][6] = { {0, 1, 2, 3, 4, 5}, {1, 0, 3, 2, 5, 4}, 2 {2, 0, 1, 4, 5, 3}, {3, 0, 4, 1, 5, 2}, 3 {4, 0, 2, 3, 5, 1}, {5, 1, 3, 2, 4, 0}}; 4 const int convert[4][6] = { {0, 1, 2, 3, 4, 5}, {0, 2, 4, 1, 3, 5}, 5 {0, 4, 3, 2, 1, 5}, {0, 3, 1, 4, 2, 5}}; 6 7 void getDice(int n, int *dice) { 8 int x = n >> 2, y = n & 3; 9 REP(i, 6) dice[i] = base[x][convert[y][i]]; 10 } 11 12 int st[4][6], mini, curID, dice[4][6]; 13 map<string, int> id; 14 15 int getID(char *s) { 16 return id.find(s) == id.end() ? id[s] = curID++ : id[s]; 17 } 18 19 void input(int n) { 20 char buf[25]; 21 curID = 0; 22 id.clear(); 23 REP(i, n) REP(j, 6) { 24 scanf("%s", buf); 25 dice[i][j] = getID(buf); 26 } 27 } 28 29 int stat[24]; 30 31 int cal(int n) { 32 int ret = 0; 33 REP(i, 6) { 34 int mx = 0; 35 _clr(stat); 36 REP(j, n) { 37 stat[dice[j][st[j][i]]]++; 38 mx = max(mx, stat[dice[j][st[j][i]]]); 39 } 40 ret += n - mx; 41 if (ret >= mini) return inf; 42 } 43 return ret; 44 } 45 46 void dfs(int n, int p) { 47 if (p >= n) { 48 mini = min(mini, cal(n)); 49 return ; 50 } 51 REP(i, 24) { 52 getDice(i, st[p]); 53 dfs(n, p + 1); 54 } 55 } 56 57 int work(int n) { 58 mini = inf; 59 getDice(0, st[0]); 60 dfs(n, 1); 61 return mini; 62 } 63 64 int main() { 65 // freopen("in", "r", stdin); 66 int n; 67 while (~scanf("%d", &n) && n) { 68 input(n); 69 printf("%d\n", work(n)); 70 } 71 return 0; 72 }
——written by Lyon