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

你可能感兴趣的:(优化,搜索,uva,剪枝,IDA)