TOJ 1551 Power Hungry Cows -- 搜索

来源:互联网 发布:数据资产化运营 编辑:程序博客网 时间:2024/06/09 20:44

题目链接:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1551

题目大意:从数对(0, 1)开始,每次可以把两个数(可以取同一个数两次)相加或相减并替换原来的任意一个数,问得到给定的p的最少操作步数。

分析:一开始想用贪心,但是很快就发现不行。。。。没办法,只能搜索。由于一次变化最多得到8个新值(可以把a, b中的任意一个变为a + a, a + b, b + b, abs(a - b)),不加很强的优化是肯定不行的。

优化1:注意a一开始为0,所以第一个非零a一定等于上一次的b,后来的a也一定在之前的b中出现过。特别地,之后的每一次a + a一定等于之前的某一个b + b,所以a + a实际上是用不着的。

优化2:其次,由于每一次变化后得到的新值new_value都是a与b的线性组合,故一定有gcd(a, b) | new_value,换言之,如果gcd(a, b)不整除p,无解。

优化3:b不可能太大,我假设的是max(a, b) <= 2p,具体证明不会(正解性也未知)。

优化4:A*算法,用step表示当前操作次数。用auxi(x)表示每次把x加倍(或减半)使x不小于(或不大于)p的最小次数,那么每次取step + auxi(max(a, b))最小的数。注意代码中那一句very very important注释,加了这一句之后速度快的不是一点点,在我自己电脑上测试p = 20000时,不加这一句时间为6312ms,加了之后为110ms。

加了这几条之后也是900+ms过的。。。

0 0