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

题目要求乘除法的最少次数,其实就是一个数组中一开始只有一个数:1 ,每次可以从数组中取两个数(可以取同一个数)相加生成一个新数加如数组 。

那么显然这是一个迭代加深搜索,从小到大枚举深度上限 。

为了降低时间复杂度,我们要尽量的减少迭代次数,所以我们优先做加法,并且优先将最大的两个数相加,这样可以最快的接近目标 。

当然,有一个很显然的剪枝: 当每次取最大的两个数相加仍然小于n时要剪枝 。因为以最快的方式增长的话其指数是按照2的幂次增加的,所以当前最大值maxv*pow(2,maxd-d) < n 时剪枝 。

数据只有1000,打表可以0ms过 。

细节见代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000+5;
int n,maxd,a[maxn];
bool dfs(int d) {
    if(a[d] == n) return true;
    if(d == maxd) return false;
    int maxv = a[0];
    for(int i=0;i<=d;i++) maxv = max(maxv,a[i]);
    if(maxv*pow(2,maxd-d) < n) return false;
    for(int i=d;i>=0;i--) {
        a[d+1] = a[d] + a[i];
        if(dfs(d+1)) return true;
        a[d+1] = a[d] - a[i];
        if(dfs(d+1)) return true;
    }
    return false;
}
int main() {
    while(~scanf("%d",&n)&&n) {
        a[0] = 1;
        for(maxd = 0; ; ++maxd) {
            if(dfs(0)) break;
        }
        printf("%d\n",maxd);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-10 15:17:25

1374 - Power Calculus (迭代加深+剪枝)的相关文章

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

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.

[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 1374 - Power Calculus——[迭代加深搜索、快速幂]

解题思路: 这是一道以快速幂计算为原理的题,实际上也属于求最短路径的题目类型.那么我们可以以当前求出的幂的集合为状态,采用IDA*方法即可求解.问题的关键在于如何剪枝效率更高.笔者采用的剪枝方法是: 1)如果当前状态幂集合中的最大元素max满足 max*2^(maxd-cur_d)<n,则剪枝.原因是:在每一次状态转移后,max最多增大一倍.(maxd-cur_d)次转移之后,max最多变成原来的2^(maxd-cur_d)倍,然而如果当前状态的极限情况下仍有max<n,则当前状态结点一定无法

POJ 3134 Power Calculus (迭代剪枝搜索)

题目大意:略 题目里所有的运算都是幂运算,所以转化成指数的加减 由于搜索层数不会超过$2*log$层,所以用一个栈存储哪些数已经被组合出来了,不必暴力枚举哪些数已经被搜出来了 然后跑$iddfs$就行了 可以加一个剪枝,设你选择的最大迭代深度为K,现在如果当前组合出的数$x$,满足$x*2^{K-dep}<n$,说明$n$一定无法被$x$组合出来(即自己不断加自己),$x$对于答案是一定无意义的,就跳出 1 #include <queue> 2 #include <cstdio&g

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

UVA 11214 Guarding the Chessboard 守卫棋盘(迭代加深+剪枝)

就是个暴力,和八皇后很像,但是还是要加一些的剪枝的. 1.最裸的暴搜 6.420s,差点超时 2.之前位置放过的就没必要在放了,每次从上一次放的位置开始放 0.400s #include<cstdio> #include<cstring> const int maxn = 11; char G[maxn][maxn]; int maxd; int n,m; bool visi[maxn],visj[maxn],vis1[maxn<<1],vis2[maxn<<

UVa 1374 Power Calculus (IDA*或都打表)

题意:给定一个数n,让你求从1至少要做多少次乘除才可以从 x 得到 xn. 析:首先这个是幂级的,次数不会很多,所以可以考虑IDA*算法,这个算法并不难,难在找乐观函数h(x), 这个题乐观函数可以是当前最大数*2maxd - d 小于n,回溯.很好理解,最大的数再一直乘2都达不到,最终肯定达不到. 再就是应该先试乘再试除,还有不要出现负整数.我测了不少知道应该是13次最多,所以这也是一个优化. 为了追求速度,也可以先1~1000的数打表. 代码如下: #include <iostream>

【UVa】1374 Power Calculus(IDA*)

题目 题目 ? ? 分析 IDA*大法好,抄了lrj代码. ? ? 代码 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxans=14; int n,a[maxans+1]; bool dfs(int d,int maxd) { if(a[d] == n) return true; if(d == maxd) return false;