这题的官方题解是高斯消元,可是本蒟蒻不会。。。
讲一下深搜的方法:
1.搜索从第一位的值开始搜,直到最后一位,判断是否合法。
2.注意剪枝防TLE。
3.三个数都是n位,最高位不能有进位。
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
const int maxn = 30;
int n;
int ans[maxn]; //赋值
char ss[4][maxn];
bool used[maxn];
int toid(char ch)
{
return ch - 'A' + 1;
}
void dfs(int x, int y, int t) //列,行,进位
{
if (!x) {
if (!t) { //最高位不能有进位
for (int i = 1; i <= n; i++) cout << ans[i] << " ";
exit(0); //相当于return 0 结束程序
}
return;
}
for (int i = x - 1; i > 0; i--) { //剪枝
int w1 = ans[toid(ss[1][i])];
int w2 = ans[toid(ss[2][i])];
int w3 = ans[toid(ss[3][i])];
if (w1 == -1 || w2 == -1 || w3 == -1) continue; //未赋值
if ((w1 + w2) % n != w3 && (w1 + w2 + 1) % n != w3) return; //无论进不进位都不成立
}
if (ans[toid(ss[y][x])] == -1) { //未赋值
for (int i = n - 1; i >= 0; i--) {
if (!used[i]) { //未使用
if (y == 3) { //第三行
int w = ans[toid(ss[1][x])] + ans[toid(ss[2][x])] + t;
if (w % n != i) continue;
used[i] = 1;
ans[toid(ss[3][x])] = i; //将该字母赋为i
dfs(x - 1, 1, w / n); //处理下一列
used[i] = 0; //回溯
ans[toid(ss[3][x])] = -1;
}
else {
used[i] = 1;
ans[toid(ss[y][x])] = i;
dfs(x, y + 1, t); //处理下一行
used[i] = 0;
ans[toid(ss[y][x])] = -1;
}
}
}
}
else {
if (y == 3) {
int w = ans[toid(ss[1][x])] + ans[toid(ss[2][x])] + t;
if (w % n != ans[toid(ss[3][x])]) return;
dfs(x - 1, 1, w / n);
}
else dfs(x, y + 1, t);
}
}
int main(void)
{
cin >> n;
memset(ans, -1, sizeof(ans));
for (int i = 1; i <= 3; i++) cin >> ss[i] + 1;
dfs(n, 1, 0); //从第n列第1行开始搜
return 0;
}