UVa1374 Power Calculus (IDA*)

题目链接

Starting with x and repeatedly multiplying by x, we can compute x31 with thirty multiplications: The operation of squaring can appreciably shorten the sequence of multiplications. The following is a way to compute x31 with eight multiplications:(略)
This is not the shortest sequence of multiplications to compute x31. There are many ways with only seven multiplications. The following is one of them:(略)
There however is no way to compute x31 with fewer multiplications. Thus this is one of the most efficient ways to compute x31 only by multiplications. If division is also available, we can find a shorter sequence of operations. It is possible to compute x31 with six operations (five multiplications and one division):(略)
This is one of the most efficient ways to compute x31 if a division is as fast as a multiplication. Your mission is to write a program to find the least number of operations to compute xn by multiplication and division starting with x for the given positive integer n. Products and quotients appearing in the sequence of operations should be x to a positive integer’s power. In other words, x−3, for example, should never appear.

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.

1.题意不再赘述,刚开始想到了快速幂,想在快速幂的过程中求出最小的步数,但实际上快速幂并不是择优选择的,而是从x1每次开方,当n&1时就乘一次x,实际上x的计算次数还是比较多的

2.看分析说是IDA*便开始构思代码。估价函数自己没想出来,但是看LRJ那么写却可以看懂(还是要多独立思考)。我们知道,每深入搜索一层,那么可以得到该层的最大数值是2当前层数,那么我们设置了最大搜索层数,如果当前的最大数值为x,x*2maxd-d<n,代表搜完规定层数的最大值仍然小于n,那么就剪枝(实际上我们发现一开始如果2maxd<n就不会搜索下去直接返回)。但是如何实现每一次搜索得到的序列集合呢,而且我们又要将集合中的元素都相互加减,那么我觉得需要数组将每个集合的存起来,还要用vis判重,但是实际上代码不许要写那么多

3.我们只用一个数组a记录到当前数x,那么我们每次只用新加入的数x对之前数组中所有的元素加减再dfs,那么可以优化很多dfs。例如刚开始只有{1},那么1对数组中所有元素加减,接下来加入了2,那么2在对{1,2}加减,这时的1就不需要再加减了(负数是需要返回的)

#include <iostream>

using namespace std;
int n,ans;
int a[1005];

bool dfs(int cur,int x,int maxd){
    if((x<<(maxd-cur))<n) return false;
    if(x<=0 || cur>maxd) return false;
    if(x==n || (x<<(maxd-cur))==n){ ans=cur; return true; };
    a[cur]=x;
    for(int i=0;i<=cur;i++){
        if(dfs(cur+1,x+a[i],maxd)) return true;
        if(dfs(cur+1,x-a[i],maxd)) return true;
    }
    return false;
}

int main()
{
    while(scanf("%d",&n) && n){
        for(int i=0;;i++){  //这里需要从0开始,没注意WA了一次
            if(dfs(0,1,i)){
                printf("%d\n",i);
                break;
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值