先来看看题目大意:
给定一个正整数n,求经过多少次乘法或除法运算可以从x得到x^n?中间结果也是可以复用的。
例如,求x^31,x^2 = x × x, x^4 = x^2 × x^2, x^8 = x^4 × x^4, x^16 = x^8 × x^8, x^32 = x^16 × x^16, x^31 = x^32 ÷ x.
至少需要6次运算,才可以得出x^31。
一拿到这个题,可能有些同学的思路是这样的,先让x^n累加,加到大于目标n时反过来减,比如473的过程:2 4 8 16 32 64 128 256 512 480 472 473共12次,512后先减32再减8加1
但是最优解却是2 4 8 16 32 31 62 126 252 504 473 共11次 ,31*2=62,62*2=126,126*2=252,252*2=504,504-31=473
所以说,一开始我们的想法就错啦,这种惯性思维不行,不行,不行,重要的事情说三遍,(我当初也是这么做的)
所以只能老实一点,搜索,怎么搜索呢,来看上面的例子,每一步都可能加上或者减去前一个已经出现的数,,有没有想法,下面来看代码,注释都在代码里面
老样子啦!!
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxans=13;//为什么是13呢,这个留给你思考,最多就到13层,
//如果多了的话就是你代码有问题了
int n,a[maxans+1]; //这个数组用来存放计算过程
bool dfs(int d,int maxd)
{
if(a[d]==n) return true; //答案来喽!!
if(d==maxd) return false; //剪枝
int maxv=a[0];
for(int i=1;i<=d;i++)
maxv=max(maxv,a[i]); //maxv表示当前计算出最大的x的幂
//printf("maxv: %d ",maxv);
if((maxv<<(maxd-d))<n) return false; //如果让maxv继续乘
//(maxd-d)次2,还小于n
//的话,说明让它以最快的
//速度增长都得不到结果
//printf("maxv: %d\n",maxv);
for(int i=d;i>=0;i--)
{
a[d+1]=a[d]+a[i]; //让d加上前面的第i个数
if(dfs(d+1,maxd)) return true;
a[d+1]=a[d]-a[i]; //让d减去前面的第i个数
if(dfs(d+1,maxd)) return true;
}
return false;
}
int solve(int n)
{
if(n==1) return 0; //奇葩数据咱们单独处理
a[0]=1; //初始化
for(int maxd=1;maxd<maxans;maxd++) //迭代加深
{
if(dfs(0,maxd)) //开始搜索
return maxd; //如果找到的话赶回当前层数
}
return maxans; //否则返回最大层数,再大也打不过它
}
int main()
{
while(~scanf("%d",&n)&&n)
{
printf("%d\n",solve(n));
}
return 0;
}
算法呢就是一个多练,多想的过程,这道题说简单也简单,说难也难,想明白了就简单了,说实话,多多练习,,不努力永远不会,让AK不再是梦。