题目
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1402
题意
4个方块,每个方块每个面涂不同的颜色,问最少重涂多少面,使四个方块相同。
思路
如刘书思路,明显,方块是可以旋转的。旋转的方式不可能多。旋转的基本操作可以定为右旋和上旋,其他所有旋转都是这两种子操作的集合。
通过搜索确定所有可能的旋转方式后,接下来就是确定该如何涂色。
选定第一个方块作为参考系,对剩下的方块分别尝试一下可能的旋转方式。确定旋转方式后,答案就很简单的相加即得。
感想
1. 三倍ice cream!
代码
#include <algorithm> #include <cassert> #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <queue> #include <tuple> #include <set> #include <map> #include <cassert> #define LOCAL_DEBUG using namespace std; const int MAXN = 5; int rightPositions[6] = { 4, 0, 2, 3, 5, 1 }; int topPositions[6] = { 3, 1, 0, 5, 4, 2 }; int n; class Status { public: int faces[6]; Status() { for (int i = 0; i < 6; i++) { faces[i] = i; } } Status(int _faces[6]) { for (int i = 0; i < 6; i++) { faces[i] = _faces[i]; } } bool operator ==(const Status & other)const { for (int i = 0; i < 6; i++) { if (faces[i] != other.faces[i])return false; } return true; } bool operator <(const Status & other)const { for (int i = 0; i < 6; i++) { if (faces[i] < other.faces[i])return true; else if (faces[i] > other.faces[i])return false; } return false; } void rotate(int positions[6]) { int tmp[6]; for (int i = 0; i < 6; i++) { tmp[i] = faces[i]; } for (int i = 0; i < 6; i++) { faces[i] = tmp[positions[i]]; } } void reRotate(int positions[6]) { int tmp[6]; for (int i = 0; i < 6; i++) { tmp[i] = faces[i]; } for (int i = 0; i < 6; i++) { faces[positions[i]] = tmp[i]; } } Status copy() { Status newStatus; for (int i = 0; i < 6; i++) { newStatus.faces[i] = faces[i]; } return newStatus; } }; set<Status> statuses; void buildStatus() { queue<Status> que; Status status; que.push(status); statuses.insert(status); while (!que.empty()) { status = que.front(); que.pop(); Status newStatus = status.copy(); newStatus.rotate(rightPositions); if (statuses.count(newStatus) == 0) { que.push(newStatus); statuses.insert(newStatus); } newStatus = status.copy(); newStatus.rotate(topPositions); if (statuses.count(newStatus) == 0) { que.push(newStatus); statuses.insert(newStatus); } } } Status cubes[MAXN]; int cnt[MAXN * 6]; int dfs(int id) { int ans = 6 * MAXN; if (id < n) { for (auto status : statuses) { cubes[id].rotate(status.faces); ans = min(dfs(id + 1), ans); cubes[id].reRotate(status.faces); } } else { ans = 0; for (int j = 0; j < 6; j++) { for (int i = 0; i < n; i++) { cnt[cubes[i].faces[j]] ++; } int best_color = 0; for (int i = 0; i < MAXN * 6; i++) { if (cnt[i] > cnt[best_color]) { best_color = i; } } ans += n - cnt[best_color]; memset(cnt, 0, sizeof(cnt)); } } return ans; } int main() { #ifdef LOCAL_DEBUG freopen("input.txt", "r", stdin); //freopen("output2.txt", "w", stdout); #endif // LOCAL_DEBUG buildStatus(); for (int ti = 1; scanf("%d", &n) == 1 && n; ti++) { map<string, int> colorNameMap; for (int i = 0; i < n; i++) { for (int j = 0; j < 6; j++) { char tmp[25]; scanf("%s", tmp); string colorName = tmp; if (colorNameMap.count(colorName) == 0) { colorNameMap[colorName] = colorNameMap.size(); } cubes[i].faces[j] = colorNameMap[colorName]; } } int ans = dfs(1); printf("%d ", ans); } return 0; }