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 || now << (MAX - cur) == n)
        return true;

    A[cur] = now;
    for (int i = 0; i <= cur; ++i) {
        if (DFS(cur + 1, now + A[i]))
            return true;
        if (DFS(cur + 1, now - A[i]))
            return true;
    }

    return false;
}

int main() {
    while (scanf("%d", &n), n) {
        for (MAX = 0; !DFS(0, 1); ++MAX);
        printf("%d\n", MAX);
    }
    return 0;
}
时间: 2024-12-14 10:43:46

UVA - 1374 Power Calculus的相关文章

[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,则当前状态结点一定无法

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 迭代深搜

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

【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;

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

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

Power Calculus 快速幂计算 (IDA*/打表)

原题:1374 - Power Calculus 题意: 求最少用几次乘法或除法,可以从x得到x^n.(每次只能从已经得到的数字里选择两个进行操作) 举例: x^31可以通过最少6次操作得到(5次乘,1次除) x^2 = x*x x^4 = (x^2)*(x^2) x^8 = (x^4)*(x^4) x^16 = (x^8)*(x^8) x^32 = (x^16)*(x^16) x^31 = (x^32)÷x 分析: 可以看到,每次从已得到的数字中选取两个操作,这样就有了枚举的思路. 这道题又是

UVa 10298 - Power Strings

题目:求一个串的最大的循环次数. 分析:dp,KMP,字符串.这里利用KMP算法. KMP的next函数是跳跃到最近的串的递归结构位置(串元素取值0 ~ len-1): 由KMP过程可知: 如果存在循环节,则S[0 ~ next[len]-1] 与 S[len-next[len] ~ len-1]相匹配: 则S[next[len] ~ len-1]就是循环节(且最小),否则next[len]为0: 因此,最大循环次数为len/(len-next[len]),最小循环节为S[next[len] ~

UVA1374 - Power Calculus(迭代深搜+剪枝)

题目链接 题意:给出x和正整数n,问最少需要几次乘除法 可以得到n = x^m 思路:其实是关于指数的操作,即从1到m最少的步数.我们可以先确定最少步数m,然后进行迭代,迭代的过程也就是判断通过相加减所得到的数可以在m次操作中等于n,如果符合,m即为最小步数,如果不符合,m++,进行下一次迭代.迭代过程中要注意剪枝,即剩余的次数如果每次都是取最大值相加还是比n小的话,就直接跳出. 代码: #include <iostream> #include <cstdio> #include