CDOJ 1085 基爷与加法等式 DFS

来源:互联网 发布:网红的淘宝杂货铺 编辑:程序博客网 时间:2024/06/06 10:59

就是给一个由字母组成的加法等式,问这个等式有多少种情况,相同字母代表相同数字,不同字母代表不同数字,不存在前导0.

呃,就是DFS搜索,但是刚开始我的姿势不对,就T了。

刚开始我是就枚举前面的所有情况,然后看得到的和能不能组成最后的和。然后,这个搜索姿势很智障地T了。。。

然后就去度娘了,,,发现要按每一位进行搜索,就是搜索所有的个位数,然后查看和的个位数是否能满足,再依次搜索十位,百位。。

这样,如果不合法,就可以很早地发现,算是一个很大的剪枝了。。

最后因为最后一个数字的长度太长和太短而错了几发,,就这样了。。


代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;char formu[12][12];int idx[27];int n, llen, maxlen;bool nozero[27];bool num[10];int DFS(int x, int y, int carry){int ans = 0;if (x == n - 1){int sum = 0;bool new_num = 0;for (int i = 0; i < n - 1; ++i)sum += idx[formu[i][y]];sum += carry;int last = sum % 10;if (idx[formu[x][y]] == -1){if (num[last]||(last==0&&nozero[formu[x][y]])){return 0;}new_num = 1;idx[formu[x][y]] = last;num[last] = 1;}else if (last != idx[formu[x][y]]){return 0;}if (y == llen - 1 && sum / 10 == 0){ans = 1;if (new_num){idx[formu[x][y]] = -1;num[last] = 0;}}else{ans = DFS(0, y + 1, sum / 10);if (new_num){idx[formu[x][y]] = -1;num[last] = 0;}}}else if (idx[formu[x][y]] == -1){int i = 0;if (nozero[formu[x][y]])i = 1;for (; i <= 9; ++i){if (num[i])continue;idx[formu[x][y]] = i;num[i] = 1;ans += DFS(x + 1, y, carry);num[i] = 0;}idx[formu[x][y]] = -1;}elseans = DFS(x + 1, y, carry);return ans;}int main(){//freopen("input.txt", "r", stdin);//freopen("output.txt", "w", stdout);while (scanf("%d", &n) != EOF){memset(num, 0, sizeof(bool) * 10);memset(formu, 0, sizeof(char) * 12 * 12);memset(idx, -1, sizeof(int) * 27);memset(nozero, 0, sizeof(bool) * 27);idx[0] = 0, maxlen = 0;int ans = 0;for (int i = 0; i < n; ++i){scanf("%s", formu[i]);int len = strlen(formu[i]);if (len > maxlen)maxlen = len;for (int j = 0; j < (len + 1) / 2; ++j){char tmp = formu[i][j] - 'A' + 1;formu[i][j] = formu[i][len - 1 - j] - 'A' + 1;formu[i][len - 1 - j] = tmp;}nozero[formu[i][len - 1]] = 1;}llen = strlen(formu[n - 1]);if (maxlen==llen)ans = DFS(0, 0, 0);printf("%d\n", ans);}//system("pause");//while (1);return 0;}

0 0
原创粉丝点击