Complete Search
枚举搜索
译 By Yahoo! Babel Fish, Nocow Aule
抛砖引玉,欢迎各位大牛不吝赐教
思想:
写枚举搜索时应遵循KISS原则(Keep it simple stupid,译为“写最单纯愚蠢的程序”,意思是应把程序写得尽量简洁),竞赛时写程序的最终目标就是在限制时间内求出解,而不需太在意否还有更快的算法。
枚举搜索具有强大的力量,他用直接面向答案并尝试所有方案的方法发现答案。这种算法几乎总是解题时你第一个想到的方法。如果它能在规定的时间与空间限制内找出解,那么它常常很容易编写与调试。这就意味着你可以有时间去解答其他难题,即那些不能显示枚举算法强大的题目。
如果你面对一道可能状态小于两百万的题目,那么你可以考虑使用枚举搜索。尝试所有的状态,看看它们是否可行。
小心!小心!
有时,题目不会直接要求你使用枚举算法。
*问题: 派对灯[IOI 98]
在一次IOI派对上有N个灯和4个灯开关,第一个开关可以使所有灯改变状态(关上开着的灯,开启关着的灯),第二个开关可以改变所有偶数位上灯的状态,第三个开关可以改变所有奇数位上灯的状态,第四个开关控制着灯1、4、7、10……(3n+1)。
告诉你N的值和所有按开关的次数(小于10,000次)。并告诉你某些灯的状态(例如:7号灯是关着的,10号灯是开着的)请编程输出所有灯可能的最后状态。
很明显,每次按开关你都要尝试4种可能。那么总共要试 410000 次(大约 106020),那意味着你没有足够的时间去使用枚举搜索,但是我们将枚举方法改进一下,那就可以使用枚举了。因为无论有多少个灯,由于开关控制的特殊性,都会出现6个灯一次循环的情况,即1号灯的状态永远与7号灯,13号灯,19号灯……相同,2号灯的状态也永远与8号灯,14号灯,20号灯……相同。同样,无论你按了多少次开关,按同一个开关两次就相当于没有按该开关,那么每一个开关就只需要考虑按一次或没有按,那么这题的枚举量就很小了。
*第3个问题: 时钟[IOI 94]
一组九个时钟在3 x 3栅格中; 其中每一个被设置到12:00、3:00、6:00或者9:00。 您的目标是操作他们全部读12:00。 不幸地,您能操作时钟的唯一的方式是九种不同类型的转动之一,每一个转动使时钟的某一子集顺时针方向90度。
找到把所有时钟拨到12:00的转动的最短序列。
要做的“明显的”事是一种递归解答,检查看是否有转动1的解答, 转动2等等,直到它发现一种解答。 这将花费9k时间, k是移动的数量。 因为k也许相当大,这不能在合理时间限制内运行完成。
注意移动的顺序不重要。 这使时间降低下来到k9,不足以改善程序运行所花费的时间。
然而,从做每个转动4次是和不做是一样的,您知道每个转动总的不会超过3次。 因此,只有49种可能性,也就是262,072;根据经验,在一秒钟内,运算次数可以超过10,000,000次(也就是一千万次)。 暴力求解,从这个角度看,是能够完美地胜任的。
样例问题 *奶牛[USACO 1996年比赛]
给出挤奶日程表(农夫A 从300时间挤奶到1000时间,农夫B 从700到1200时间等等),计算
* 至少一头母牛被挤奶的最长时间 * 没有母牛被挤奶的最长时间
完全母牛&亲和母牛表兄弟[USACO 1995 Final Round]
完全数是真因子(即除了本身之外的约数)的和等于本身的数。 例如, 28 = 1 + 2 + 4 + 7 + 14。一对亲和数(又叫相亲数)是其中任一个数的所有真因数之和等于另一个数的一对数字。当然,亲和数链(也叫相亲数链)就是第一个数的真因数之和等于第二个数,第二个数的真因数之和等于第三个……等等,直到最后一个数的真因数之和等于第一个数。
农夫约翰的大农场里的每头母牛按顺序从1到32000有一个编号。一头编号是完全数的母牛就是完全母牛。 如果他们的编号形成了一个亲和数链,这些母牛就互相是亲和母牛表兄弟。 找出所有完全母牛和亲和母牛表兄弟。