链接
题目描述
有三个字符串,现在这三个字符串用一些大写字母代替,每个字母代表一个数字,相同的字母为相同的数字,现在要给出每个字母对应的数字,使得加法成立
字母是按A往后去计,有多少个字母就是多少进制
输入
5
ABCED
BDACE
EBBAA
输出
1 0 3 4 2
思路
考虑深搜,枚举每一个字母可能对应的数字
然后剪枝
设 t t t为上一位加完之后的进位
那么很显然
若满足 a + b + t ≠ c a+b+t \neq c a+b+t=c则显然当前枚举情况是错误的
若满足当前是最后一位且 a + b > n a+b>n a+b>n那么肯定也是错的,因为最高只有n位,不可能进位
因为是加法, 那么进位仅可能是0或1
那么如果满足 a + b ≠ c a+b \neq c a+b=c 且 a + b + 1 ≠ c a+b+1 \neq c a+b+1=c那么当前情况也是错误的
因此得到剪枝的策略,直接深搜就可以了
代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n, num;
int shu[105], used[555], chi[1005];
char vis[1005], s[55][1005];
bool check() {
int x = 0;
for (int i = n; i >= 1; --i) {
int a = shu[s[1][i] - 'A'];
int b = shu[s[2][i] - 'A'];
int c = shu[s[3][i] - 'A'];
if (a != -1 && b != -1 && c != -1) {
if (x != -1) {
if ((a + b + x) % n != c)
return 0;//如上情况1
if (i == 1 && a + b + x >= n)
return 0;//如上情况2
x = (a + b + x) / n;
} else {
if ((a + b) % n != c && (a + b + 1) % n != c)//如上情况3
return 0;
if (i == 1 && a + b >= n)
return 0;
}
} else
x = -1;
}
return 1;
}
bool dfs(int x) {
if (num + 1 == x)
return 1;
for (int i = 0; i < n; ++i)
if (!used[i]) {
used[i] = 1;
shu[chi[x] - 'A'] = i;
if (check() && dfs(x + 1))
return 1;
shu[chi[x] - 'A'] = -1;
used[i] = 0;
}//模拟每一个字母
return 0;
}
int main() {
memset(shu, -1, sizeof(shu));
scanf("%d", &n);
for (int i = 1; i <= 3; ++i) scanf("%s", s[i] + 1);
for (int j = n; j >= 1; --j)
for (int i = 1; i <= 3; ++i)
if (!vis[s[i][j] - 'A']) {
vis[s[i][j] - 'A'] = 1;
chi[++num] = s[i][j];
}//记录出现了那些字母
dfs(1);
for (int i = 0; i < n; ++i) printf("%d ", shu[i]);
return 0;
}