看到题目,必然是宽搜无疑了
主要是对于状态的储存方法,一开始我很脑残的用 9 进制数来存状态,写到一半发现内存会超。。
重新考虑下,因为最多只有 8! 种状态,所以直接存每种状态有没有出现过是可行的。
TRANS 函数将每个状态映射到一个数(按 1 到 8 的全排列 从小到大顺序第 k 个, 就把当前状态映射到 k )
比如 1 2 3 4 5 6 7 8 映射到 1, 2 1 3 4 5 6 7 8 映射到 7! + 1
状态的转换我是直接对数进行操作, 若当前状态为1 2 3 4 5 6 7 8, 就 看做一个数 12345678。
思想就是提取每一位的数字重新组合成新数,具体实现见代码,应该还是比较好理解的。
/*
PROG:msquare
LANG:C++
*/
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 500000;
const int initial = 12345678;
const int digit[8] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000};
const int fac[8] = {1, 1, 2, 6, 24, 120, 720, 5040};
bool hash[50000], used[10];
int pre[N], a[N], ans[N], goal, tot, head, tail, x, now;
char change[N];
int transA(int now)
{
int tmp = 0;
tmp += (now % digit[1] * digit[7]);
tmp += (now / digit[1] % digit[1] * digit[6]);
tmp += (now / digit[2] % digit[1] * digit[5]);
tmp += (now / digit[3] % digit[1] * digit[4]);
tmp += (now / digit[4] % digit[1] * digit[3]);
tmp += (now / digit[5] % digit[1] * digit[2]);
tmp += (now / digit[6] % digit[1] * digit[1]);
tmp += (now / digit[7] % digit[1] * digit[0]);
return tmp;
}
int transB(int now)
{
int tmp = 0;
tmp += (now / digit[4] % digit[1] * digit[7]);
tmp += (now / digit[5] * digit[4]);
tmp += (now % digit[3] * digit[1]);
tmp += (now / digit[3] % digit[1]);
return tmp;
}
int transC(int now)
{
int tmp = 0;
tmp += (now / digit[7] * digit[7]);
tmp += (now / digit[1] % digit[1] * digit[6]);
tmp += (now / digit[6] % digit[1] * digit[5]);
tmp += (now / digit[3] % digit[2] * digit[3]);
tmp += (now / digit[5] % digit[1] * digit[2]);
tmp += (now / digit[2] % digit[1] * digit[1]);
tmp += (now % digit[1]);
return tmp;
}
int trans(int now, int step)
{
if (step == 0) return 1;
int tmp = now / digit[step];
int cnt = 0;
for (int i = 1;i != tmp;++i)
{
if (!used[i])
++cnt;
}
used[tmp] = 1;
return cnt * fac[step] + trans(now % digit[step], step-1);
}
int main()
{
freopen("msquare.in", "r", stdin);
freopen("msquare.out", "w", stdout);
for (int i = 0;i < 8;++i)
{
scanf("%d", &x);
goal = goal * 10 + x;
}
head = 0, tail = 1;
a[head] = initial;
while (head < tail)
{
memset(used, 0, sizeof(used));
now = a[head++];
int tmp = trans(now, 7);
if (now == goal) break;
if (hash[tmp]) continue;
change[tail] = 'A', pre[tail] = head-1, a[tail++] = transA(now);
change[tail] = 'B', pre[tail] = head-1, a[tail++] = transB(now);
change[tail] = 'C', pre[tail] = head-1, a[tail++] = transC(now);
hash[tmp] = 1;
}
int k = head-1;
while (k != 0)
{
ans[++tot] = change[k];
k = pre[k];
}
printf("%d\n", tot);
for (int i = tot;i > 0;--i) printf("%c", ans[i]);
printf("\n");
}