题目链接
题意
求最少需要几次乘除法可以从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;
}