CDOJ 1085 基爷与加法等式 DFS

就是给一个由字母组成的加法等式,问这个等式有多少种情况,相同字母代表相同数字,不同字母代表不同数字,不存在前导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;
	}
	else
		ans = 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;
}

你可能感兴趣的:(CDOJ 1085 基爷与加法等式 DFS)