这里给大家分享一个和图形变换有关的暴力枚举
我觉得有时候,解决图形的变换问题,引入一些群论的思想,会好理解很多
群论思想介绍如下
$\text{change posture of cubes}$
改变 $\textbf{cubes}$ 的 $\textbf{posture}$
本质是一个$\textbf{置换(permutation)}$
由 $\Omega \rightarrow \Omega$ 的变换组成的集合称为置换
$S_n = S(\Omega)$
$\textbf{i) } S_n \text{ 的单位元定义: } \forall \pi \in S_n, \ \pi e = \pi = e\pi$
$\quad e:= \textbf{for } \forall i \in [1, n]$
$\quad \quad \quad A(i) = i$
$\textbf{ii) } \pi: i \mapsto \pi(i), i = 1, 2, \cdots, n$
$$
\pi:\left(\begin{array}{ccc}
1 & 2 & \ldots & n \\\
i_{1} & i_{2} & \ldots & i_{n}
\end{array}\right) \\\ \ \\\
i_k \in \{1, 2, \cdots, n\}
$$
其本质是构成了一个$\textbf{全排列映射}$
$$ \pi:\left(\begin{array}{ccc} 1 & 2 & \ldots & n \\\ \downarrow & \downarrow & \ & \downarrow \\\ i_{1} & i_{2} & \ldots & i_{n} \end{array}\right) $$
$\textbf{iii) } S_n \text{上的乘法运算其实是置换的合成}$
$\quad \text{ 构成了} \textbf{ n 元对称群}$
$\textbf{example}$
$\textbf{algorithm1}$
$\textbf{permutation groups}$
$\textbf{i) for } \forall i \in [1, n], e:\Rightarrow A(i) = i$
$\textbf{ii) }$
$$
\pi_{\textbf{left}} A= D \Rightarrow \\ \ \\
\textbf{trans} = \pi_{\textbf{left}}, \quad \textbf{rot(trans, A):}
$$
$\quad \textbf{for } \forall i \in [1, n], \textbf{let } e = [A(i)]$
$\quad \quad \text{eg: }\quad \pi_{\textbf{left}}(i) = p$
$\quad \quad D=\pi^{k} = (\pi_k\pi_{k-1}\cdots \pi_2\pi_1) e$
$\quad \quad D(i) = \textbf{trans(A(i))}, \text{ return } D$
$\textbf{algorithm2 逆运算}$
$$
(\pi_1 \pi_2 \cdots \pi_k) A = D \Longrightarrow \\ \ \\
A = (\pi_k^{-1})(\pi_{k-1}^{-1}) \cdots (\pi_1^{-1})D
$$
$\textbf{permutation inversion}$
$\quad \textbf{for } \forall x \in [1, n]$
$\quad \quad \ \pi(x) = p$
$\quad \quad \ \textbf{do } A(p) \gets A(x)$
$\textbf{main algorithm}$
$\textbf{check()}$
$\text{get inversion: } ori(i) \gets cube(i)$
$\textbf{for } \forall k \in \textbf{faces}[0, 1, \cdots, 5], \textbf{tot} = 0$
$\quad \text{ get }\textbf{ Max-color}$
$\quad \textbf{ for } \forall i \in \textbf{ori}[1, \cdots, n]$
$\quad \quad \textbf{ Max-color=} \max(\textbf{Max-color}, \textbf{ cnt}(ori(i, k)))$
$\quad \textbf{ tot} = \sum (n - \textbf{colored-Max-face})$
$\textbf{ans = } \min(\textbf{ans, tot})$
$\textbf{dfs}(d)$
$\quad \ \textbf{for } \forall i \in [0, 23)$
$\quad \quad \ \text{cube(d) shapes as } \textbf{posture } R(d) = i$
$\quad \quad \ \textbf{dfs}(d + 1)$
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <bitset>
#include <assert.h>
using namespace std;
typedef long long ll;
typedef set<int>::iterator ssii;
#define Cmp(a, b) memcmp(a, b, sizeof(b))
#define Cpy(a, b) memcpy(a, b, sizeof(b))
#define Set(a, v) memset(a, v, sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define _forS(i, l, r) for(set<int>::iterator i = (l); i != (r); i++)
#define _rep(i, l, r) for(int i = (l); i <= (r); i++)
#define _for(i, l, r) for(int i = (l); i < (r); i++)
#define _forDown(i, l, r) for(int i = (l); i >= r; i--)
#define debug_(ch, i) printf(#ch"[%d]: %d\n", i, ch[i])
#define debug_m(mp, p) printf(#mp"[%d]: %d\n", p->first, p->second)
#define debugS(str) cout << "dbg: " << str << endl;
#define debugArr(arr, x, y) _for(i, 0, x) { _for(j, 0, y) printf("%c", arr[i][j]); printf("\n"); }
#define _forPlus(i, l, d, r) for(int i = (l); i + d < (r); i++)
#define lowbit(i) (i & (-i))
#define MPR(a, b) make_pair(a, b)
// == enumerate permutation ==
/*
int LEFT[] = {4, 0, 2, 3, 5, 1};
int UP[] = {2, 1, 5, 0, 4, 3};
void rot(int *trans, int *A) {
int q[6];
memcpy(q, A, sizeof(q));
_for(i, 0, 6) A[i] = trans[q[i]];
}
void enumerate() {
int E[6] = {0, 1, 2, 3, 4, 5};
_for(i, 0, 6) {
int A[6];
memcpy(A, E, sizeof(E));
if(i == 0) rot(UP, A);
if(i == 1) {
rot(LEFT, A);
rot(UP, A);
}
if(i == 3) {
rot(UP, A);
rot(UP, A);
}
if(i == 4) {
rot(LEFT, A);
rot(LEFT, A);
rot(LEFT, A);
rot(UP, A);
}
if(i == 5) {
rot(LEFT, A);
rot(LEFT, A);
rot(UP, A);
}
_for(k, 0, 4) {
printf("{%d, %d, %d, %d, %d, %d},\n", A[0], A[1], A[2], A[3], A[4], A[5]);
rot(LEFT, A);
}
}
}
// == enumerate finsihed ==
int main() {
freopen("out.txt", "w", stdout);
enumerate();
}
*/
/*
{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},
*/
const int D[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}
};
// D[r[i]] get posture of ith cube
int n;
const int maxn = 4;
int ori[maxn][6];
int cube[maxn][6];
int r[maxn];
int ans;
vector<string> data;
void init() {
ans = n * 6;
data.clear();
Set(r, 0);
}
inline int getID(const char *name) {
string str(name);
_for(i, 0, data.size()) {
if(data[i] == str) return i;
}
data.push_back(str);
return data.size() - 1;
}
// == check ==
void inv(int ori[][6], const int cube[][6]) {
_for(i, 0, n) _for(j, 0, 6) {
int p = D[r[i]][j];
ori[i][p] = cube[i][j];
}
}
void check() {
inv(ori, cube);
int tot = 0;
_for(k, 0, 6) {
int Max = 0;
int cnt[maxn * 6];
Set(cnt, 0);
_for(i, 0, n) Max = max(Max, ++cnt[ori[i][k]]);
tot += n - Max;
}
ans = min(ans, tot);
}
// == check finished ==
// == dfs ==
void dfs(int d) {
if(d == n) check();
else {
_for(i, 0, 24) {
r[d] = i;
dfs(d + 1);
}
}
}
// == dfs finished ==
int main() {
freopen("input.txt", "r", stdin);
while (scanf("%d", &n) == 1 && n) {
init();
// get data of cubes
_for(i, 0, n) _for(j, 0, 6) {
char name[30];
scanf("%s", name);
cube[i][j] = getID(name);
}
dfs(1);
printf("%d\n", ans);
}
}
看了下空间,用c++的大佬。
应该是弄算法的在读大佬吧
我前端工程师,主写JavaScript,业余爱好算法写c++
退役大佬吗?
我觉得您代码没冗余的设计模式继承啥的,c++写的很精简的那种。 没有工程的那种味道,听厉害的
嗯,工程代码我不写c的,c写工程太烦了
其实很多继承之类的,写c++是为了方便别人更好的补充功能,我会把一些可能需要的东西给封装起来。。比如说,位运算,群运算等等,我这个这样写,转工程也很简单,弄个继承的接口,方便别人重写。。。比如我现在这篇文章讲的是置换运算,其实群运算,还很多,这个就可以弄成继承来做。。。有些是没有必要的
看工程和看算法是不一样的,目的不同吧。
orz
%%%%%