UVA - 1374 Power Calculus(IDA*+剪枝)

题目链接
题意

求最少需要几次乘除法可以从x得到x^n?

思路

也就是求1经过最少加减可以得出n
序列初始只有1,每次选任意两数进行加减,加入序列
使用IDA*迭代加深搜索

剪枝条件

当前序列最大值*(2^max-步数) < n 即后边步数一直按最快的求法仍然比n小

优化方案

1.迭代的max值不从1开始,而是从log(n)开始
2.每次只对最大值进行加减操作
3.当最大值大于n时只进行减操作

代码

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;

int d[1001];
bool f[2001];
int len;
int m;

bool ida_star(int n, int max, int now)
{
    if(now > max ||m*(1<<(max-now)) < n)
        return false;

    if(f[n])
        return true;

    for(int i = len-1; i >= 0 && m < n; --i)
    {
        if(!f[d[i]+m])
        {
            m += d[i];
            d[len++] = m;
            f[m] = 1;
            if(ida_star(n, max, now+1))
               return true;
            len--;
            f[m] = 0;
            m -= d[i];
        }
    }
    for(int i = 0; i < len ; ++i)
    {
        if(!f[m - d[i]])
        {
            d[len++] = m - d[i];
            f[m - d[i]] = 1;
            if(ida_star(n, max, now+1))
                return true;
            len--;
            f[m - d[i]] = 0;
        }
    }
    return false;
}

int init(int n)
{
    int ans = 0;
    int p = 1;
    while(p <= n)
    {
        ++ans;
        p <<= 1;
    }
    return ans;
}

int main()
{
    int i;
    while(cin>>i && i)
    {
        for(int j = init(i); ; ++j)
        {
            memset(f, 0, sizeof(f));
            len = m = d[0] = f[1] = f[0] = 1;
            if(ida_star(i, j, 0))
            {
                cout<<j<<endl;
                break;
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值