ACDREAM 05D 哗啦啦族的加法计算
Problem Description
小彭玉今天开始学习加法啦!
唐老师写了个加法等式,小彭玉扑通扑通就凑出来了一种合法解
唐老师又写了个加法等式,然后想问你,这个加法等式究竟有多少种可行解呢?
Input
输入包含多组数据。
每组数据第一行一个整数n,表示有n个字符串 3 ≤ n ≤ 10
接下来n行,每行有1个最多只含10个大写字母的字符串,前 n - 1 行的字符串表示加数,第 n 行的字符串表示和
每个样例最多只有26个互不相同的大写字母,每个字母表示 0 - 9 中的一个数,相同字母表示相同的数,不同字母表示不同的数输入包含多组数据。
Output
对于每组数据输出一个整数,表示不同的可行解的数量。
对于两个可行解,只要有一个字母表示不同的数字,我们就认为这两个可行解不同
Sample Input
4
TAI
SHEN
LA
ACER
Sample Output
76
题目大意:由26个字母组成的竖式加法,一个字母对应一个数字(0~9,不会同时出现10个不同的字母),问有几种映射是满足这个竖式的。
解题思路:注意竖式上的数不能有前导零。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <map>
using namespace std;
typedef long long ll;
int n;
char s[15][15];
int vis[10];
int len[15], Max, ans;
int mp[30];
bool check() {
for(int i = 1; i <= n; i++) {
int len = strlen(s[i]);
if(mp[s[i][len-1] - 'A'] == 0)
return false;
}
return true;
}
void dfs(int x, int y, int sum) {
if(x == n) {
if(y == Max - 1) {
if(sum / 10 == 0) {
if(mp[s[x][y] - 'A'] == -1 && check() && !vis[sum % 10]) {
ans++;
}else if(mp[s[x][y] - 'A'] == sum % 10 && check()) {
ans++;
}
}
}else if(mp[s[x][y] - 'A'] != -1) {
if(sum % 10 == mp[s[x][y] - 'A'])
dfs(1, y + 1, sum / 10);
}else {
if(!vis[sum % 10]) {
mp[s[x][y] - 'A'] = sum % 10;
vis[sum % 10] = true;
dfs(1, y + 1, sum / 10);
mp[s[x][y] - 'A'] = -1;
vis[sum % 10] = false;
}
}
return ;
}else {
if(s[x][y] == 0) {
dfs(x + 1, y, sum);
}else if(mp[s[x][y] - 'A'] != -1) {
dfs(x + 1, y, sum + mp[s[x][y] - 'A']);
}else {
for(int i = 0; i < 10; i++) {
if(!vis[i]) {
mp[s[x][y] - 'A'] = i;
vis[i] = true;
dfs(x + 1, y, sum + i);
mp[s[x][y] - 'A'] = -1;
vis[i] = false;
}
}
}
}
}
int main() {
while (scanf("%d\n", &n) != EOF) {
memset(vis, 0, sizeof(vis));
memset(mp, -1, sizeof(mp));
memset(s, 0, sizeof(s));
Max = 0;
for (int i = 1; i <= n; i++) {
scanf("%s", s[i]);
len[i] = strlen(s[i]);
Max = max(Max, len[i]);
reverse(s[i], s[i] + len[i]);
}
ans = 0;
dfs(1, 0, 0);
printf("%d\n", ans);
}
return 0;
}