UVa 1374 - Power Calculus——[迭代加深搜索、快速幂]

解题思路:

  这是一道以快速幂计算为原理的题,实际上也属于求最短路径的题目类型。那么我们可以以当前求出的幂的集合为状态,采用IDA*方法即可求解。问题的关键在于如何剪枝效率更高。笔者采用的剪枝方法是:

  1)如果当前状态幂集合中的最大元素max满足 max*2^(maxd-cur_d)<n,则剪枝。原因是:在每一次状态转移后,max最多增大一倍。(maxd-cur_d)次转移之后,max最多变成原来的2^(maxd-cur_d)倍,然而如果当前状态的极限情况下仍有max<n,则当前状态结点一定无法出解。

  2)解的幂集合中最多只有一个元素比目标n大。

采用反证法,证明如下:

  假设解的幂集合中存在m2>m1>n ,那么必然存在从m2到达m1的路径p1,和从m1到达n的路径p2(否则与假设矛盾)。

  设路径p1花费步数s1,路径p2花费步数s2,那么从m2到达n的步数为s3=s2+s1>s2。

  然而由于我们采用IDA*算法,由于s2<s3,路径p2会先被找到,当前状态不会出现,产生矛盾,得证。

有了以上优化思路,代码效率将会极大提高。

代码如下:

 1 #include <iostream>
 2 #include <vector>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <ctime>
 6 #include <set>
 7 #include <algorithm>
 8
 9 using namespace std;
10 #define time__ printf("time : %f\n",double(clock())/CLOCKS_PER_SEC)
11
12 int tar_n;
13 int power[3000+5];
14 vector<int> S;
15 int maxd;
16 int S_upper_n(){
17     int cnt=0;
18     for(int i=0;i<S.size();i++)
19         if(S[i]>tar_n) cnt++;
20     return cnt;
21 }
22 bool dfs(int d){
23     if(d==maxd){
24         if(power[tar_n]) return true;
25         else return false;
26     }
27     int S_max=0;
28     for(int i=0;i<S.size();i++)
29         S_max=max(S_max,S[i]);
30     if(((S_max)<<(maxd-d))<tar_n||S_upper_n()>1)
31         return false;
32     for(int i=S.size()-1;i>=0;i--){
33         int t;
34         t=S[S.size()-1]+S[i];
35         if(power[t]==0){
36             S.push_back(t);
37             power[t]=1;
38             if(dfs(d+1)) return true;
39             S.pop_back();
40             power[t]=0;
41         }
42         t=S[S.size()-1]-S[i];
43         if(t>0&&power[t]==0){
44             S.push_back(t);
45             power[t]=1;
46             if(dfs(d+1)) return true;
47             S.pop_back();
48             power[t]=0;
49         }
50     }
51     return false;
52 }
53 bool solve(){
54     memset(power, 0, sizeof power);
55     S.clear();
56     S.push_back(1);
57     power[1]=1;
58     if(dfs(0))
59         return true;
60     return false;
61 }
62 int main() {
63     while(scanf("%d",&tar_n)&&tar_n){
64         maxd=0;
65         int temp=1;
66         while(temp<tar_n){
67             maxd++;
68             temp+=temp;
69         }
70         for(;;maxd++)
71             if(solve()){
72                 printf("%d\n",maxd);
73                 //time__;
74                 break;
75             }
76     }
77     //time__;
78     return 0;
79 }
时间: 2024-12-26 02:43:56

UVa 1374 - Power Calculus——[迭代加深搜索、快速幂]的相关文章

1374 - Power Calculus (迭代加深+剪枝)

题目要求乘除法的最少次数,其实就是一个数组中一开始只有一个数:1 ,每次可以从数组中取两个数(可以取同一个数)相加生成一个新数加如数组 . 那么显然这是一个迭代加深搜索,从小到大枚举深度上限 . 为了降低时间复杂度,我们要尽量的减少迭代次数,所以我们优先做加法,并且优先将最大的两个数相加,这样可以最快的接近目标 . 当然,有一个很显然的剪枝: 当每次取最大的两个数相加仍然小于n时要剪枝 .因为以最快的方式增长的话其指数是按照2的幂次增加的,所以当前最大值maxv*pow(2,maxd-d) <

[2016-03-03][UVA][1374][Power Calculus]

[2016-03-03][UVA][1374][Power Calculus] 时间:2016-03-03 16:14:01 星期四 题目编号:UVA 1374 题目大意:给出x的指数n,问,x经过多少次相乘才能得到x^n 输入:n 输出:次数 分析: 求乘法的所有可能方式,用dfs,适当剪枝优化,变成IDA* x的乘法,变成了指数的加法 每次不断平方,最少次数 为 不断平方的次数.这个为maxd起点 方法: 枚举每一位出现过的次数,当前字数加上枚举出来的次数,进入下一层dfs 剪枝:如果预计最

uva 11212 - Editing a Book(迭代加深搜索 IDA*) 迭代加深搜索

迭代加深搜索 自己看的时候第一遍更本就看不懂..是很水,但智商捉急也是没有办法的事情. 好在有几个同学已经是做过了这道题并且对迭代加深搜索的思路有了一定的了解,所以在某些不理解的地方询问了一下他们的见解, 真的是很有帮助,也许自己想要想很久才能想明白,还会很痛苦,稍微问一下别人的想法,点上一个方向,剩下的自己就能想得明白了. 迭代加深. 把answer(需要的步数或其他)在主函数里面从零往上递加,此之谓 "层数",亦可谓之"深度".用书上的话就是: 从小到大枚举深度

UVA 1343 - The Rotation Game-[IDA*迭代加深搜索]

解题思路: 这是紫书上的一道题,一开始笔者按照书上的思路采用状态空间搜索,想了很多办法优化可是仍然超时,时间消耗大的原因是主要是: 1)状态转移代价很大,一次需要向八个方向寻找: 2)哈希表更新频繁: 3)采用广度优先搜索结点数越来越多,耗时过大: 经过简单计算,最长大概10次左右的变换就能出解,于是笔者就尝试采用IDA*,迭代加深搜索的好处是: 1)无需存储状态,节约时间和空间: 2)深度优先搜索查找的结点数少: 3)递归方便剪枝: 代码如下: 1 #include <iostream> 2

UVA 11212 Editing a Book [迭代加深搜索IDA*]

11212 Editing a Book You have n equal-length paragraphs numbered 1 to n. Now you want to arrange them in the order of 1, 2, . . . , n. With the help of a clipboard, you can easily do this: Ctrl-X (cut) and Ctrl-V (paste) several times. You cannot cut

poj 3134 Power Calculus(迭代加深dfs+强剪枝)

Description Starting with x and repeatedly multiplying by x, we can compute x31 with thirty multiplications: x2 = x × x, x3 = x2 × x, x4 = x3 × x, …, x31 = x30 × x. The operation of squaring can be appreciably shorten the sequence of multiplications.

UVA - 1374 Power Calculus 迭代深搜

题目大意:问从1变到n至少需要多少步.变换规则如下 1.变化过程中的中间结果可以任意使用 2.每次只能挑选两个数进行加减 解题思路:先算一下至少需要多少步,然后在如果在当前步数下无法到达结果的话,就当前步数加1,继续搜索下去 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define maxn 1010 int num[maxn], cnt, n ,MIN_dep

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 inp

UVA - 1374 Power Calculus

题目大意:给出 n,问说至少计算几步得到 x^n. 解题思路:迭代深搜,枚举步数,然后深搜判断是否可行.需要优化,当当前数 now 按照最大方案执行后仍然小于 n,则说明不可行. #include <cstdio> int n, MAX, A[35]; bool DFS(int cur, int now){ if (cur > MAX || now <= 0 || now << (MAX - cur) < n) return false; if (now == n