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

来源:互联网 发布:淘宝流量接单任务平台 编辑:程序博客网 时间:2024/05/22 11:32

题目链接
题意

求最少需要几次乘除法可以从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
原创粉丝点击