[BZOJ1902]:[NOIP2004]虫食算(搜索)

题目传送门


题目描述:

所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母。

来看一个简单的例子:

  43#98650#45+8468#6633=44445506978

其中#号代表被虫子啃掉的数字。根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5。 现在,我们对问题做两个限制: 首先,我们只考虑加法的虫食算。这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0。 其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的。我们将相同的数字用相同的字母表示,不同的数字用不同的字母表示。如果这个算式是N进制的,我们就取英文字母表中的前N个大写字母来表示这个算式中的0到N-1这N个不同的数字(但是这N个字母并不一定顺序地代表0到N-1)。输入数据保证N个字母分别至少出现一次。

    BADC+CBDA=DCCC

上面的算式是一个4进制的算式。很显然,我们只要让ABCD分别代表0123,便可以让这个式子成立了。你的任务是,对于给定的N进制加法算式,求出N个不同的字母分别代表的数字,使得该加法算式成立。输入数据保证有且仅有一组解。


输入格式:
包含4行。第一行有一个正整数N,后面的3行每行有一个由大写字母组成的字符串,分别代表两个加数以及和。这3个字符串左右两端都没有空格,从高位到低位,并且恰好有N位。


输出格式:

包含一行。在这一行中,应当包含唯一的那组解。解是这样表示的:输出N个数字,分别表示A,B,C……所代表的数字,相邻的两个数字用一个空格隔开,不能有多余的空格。


样例:

样例输入:

5
ABCED
BDACE
EBBAA

样例输出:

1 0 3 4 2


数据范围与提示:

对于全部的数据,保证有N≤26。


题解:

官方正解是高斯消元,不得不承认高斯消元用来做这道题的确要比搜索简单。

先来算一下时间复杂度,高斯消元:O(n3),搜索:O(nn)。

不管你怎么说,我感觉nn挺帅的。

所以我就去搜索了哇~

显然不能直接爆搜,卡长卡的好没准能跑过n=9,n≥10想都别想了。

那么考虑剪枝:

为简便,地一个字符串称为A,第二个字符串称为B,第三个字符串称为C。

首先你肯定会想到,如果A+B肯定不能得到C,那么就不要往下搜了。

这里需要注意的是,有可能会存在进位。

然后接着考虑,小学的时候数学老师教给你竖式加法的时候,我们都是从最右边网左算。

那么转换到这道题,我们也可以从右往左搜,这样就能更快的把枝剪掉了(注意你的judge函数要优秀)。

还有一种情况,就是如果最前面出现了进位,那么是要剪掉的,所以我们先搜大的数可以更快的出现进位,进而更快的剪掉这个枝。

所以从大往小搜必不可少。

有了这些我就可以轻松A掉这道题了,但是作为一名卓越的OIER,我们还要考虑怎么让代码跑的更快。

所以我就讲一下所有的剪枝:

1.最前面出现进位直接return false,或者A和B串开头位相加比C串开头位大,也要return false。

2.从左往右开始judge,首先,在A,B,C串都没有出现有字母没有赋值的情况的时候,可以按照严格的带进位的加法进行判断。

3.在出现了一个数没有赋值之后,我们就要按照考虑进位与不进位开始考虑了。

  α.最好想到的就是无论进不进位都无法满足的话,就return false。

  β.如果当前位有两个数已经赋值,一个数还没有赋值,那么如果根据这两个数所算出来的第三个数已经被使用(赋值不能重复),那么可以提前剪掉。

如果这些都能满足的话,则继续往前搜。


代码时刻:

未完……

猜你喜欢

转载自www.cnblogs.com/wzc521/p/11137584.html