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

1 31 70 91 473 512 811 953 0
 

 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 }

 

转载于:https://www.cnblogs.com/npugen/p/9550669.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值