UVA1374-Power Calculus(迭代加深搜索)
Problem UVA1374-Power Calculus
Accept:323 Submit:2083
Time Limit: 3000 mSec
Problem Description
Input
The input is a sequence of one or more lines each containing a single integer n. n is positive and less than or equal to 1000. The end of the input is indicated by a zero.
Output
Your program should print the least total number of multiplications and divisions required to compute xn starting with x for the integer n. The numbers should be written each in a separate line without any superfluous characters such as leading or trailing spaces.
Sample Input
Sample Ouput
0
6
8
9
11
9
13
12
题解:IDA*算法,思路很直接,剪枝也很明显,就是如果目前最大的数,在接下来的几轮迭代中如果每次都翻倍还到不了n就剪枝。
还有一个神奇的剪枝就是每次都要利用到最后生成的那个数(不知道为啥)。
我一开始使用set进行集合操作,但是多了个log就让效率崩了,13层的就很难输出了,看了lrj的代码改成数组效率大大提高,以后在注重效率的地方还是尽量少用STL。
这个题让我比较困惑的是在代码中如果没有当 d == maxd 时return false;就会出现神奇的错误,而前几道IDA*的题目在这一点上都不太重要,冥思苦想,大概知道为啥了。
前几道类似的题目不会出现d超过maxd还能继续递归下去的情况(由估价函数可以清楚看到),但是这个题不一样,从估价函数中可以看到(见代码),这样的情况是完全可能出现的,因此可能这次递归开始设置的阈值是10,但是到10没停下来,继续深度递归,然后返回true导致程序误以为在这个阈值时正好搜索到结果,输出错误结果,这个点以后一定要注意,或者干脆每次写都加上这句,对效率应该不会有大的影响,理解不对的地方请大佬指教。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <set> 6 7 using namespace std; 8 9 const int maxn = 15; 10 11 int n,maxd; 12 int a[maxn+1]; 13 14 bool dfs(int d) { 15 if (a[d] == n) return true; 16 if (d == maxd) return false; 17 18 int Max = a[0]; 19 for (int i = 0; i <= d; i++) { 20 Max = Max > a[i] ? Max : a[i]; 21 } 22 if ((Max << (maxd - d)) < n) return false; 23 24 for (int i = d; i >= 0; i--) { 25 a[d + 1] = a[d] + a[i]; 26 if (dfs(d + 1)) return true; 27 a[d + 1] = a[d] - a[i]; 28 if (dfs(d + 1)) return true; 29 } 30 return false; 31 } 32 33 int main() 34 { 35 //freopen("input.txt", "r", stdin); 36 while (scanf("%d", &n) == 1 && n) { 37 if (n == 1) { 38 printf("0\n"); 39 continue; 40 } 41 memset(a, 0, sizeof(a)); 42 a[0] = 1; 43 for (maxd = 1;; maxd++) { 44 if(dfs(0)) break; 45 } 46 printf("%d\n", maxd); 47 } 48 return 0; 49 }