题意:问最少经过多少次乘除法混合运算之后,可以用(x)计算得到(x^n)。可以使用中间值,但不能出现负次方幂。
思路:因为(n<≤1000),可以直接用一个数组记录得到的中间值。每一次用当前得到的数进行下一步计算,都遍历一次所有中间值,乘和除都试一遍就好了。
但如果单纯DFS,其中有一条路会无限乘下去,这显然是不行的。因此需要一个约束值(maxh),以及估算的边界(maxh-cur),如果当前指数的(2^{maxh-cur})倍仍小于(n),说明答案在更深处,(maxh)小了,需要迭代加深。
注意(maxh)表示的就是最小的计算次数,最后答案就是它。
int n, maxh;
int rec[1010];
bool dfs(int x, int cur) {
//当前计算到的指数为x,中间已经算到了cur个指数
if ((x << maxh - cur) < n) return false;
//当前指数的2^(maxh-cur)倍也达不到n,说明答案在更深处
if (cur > maxh) return false;
//超过深度约束值,仍搜不到
rec[cur] = x;
if (x == n) return true;
//用之前算到过的指数乘/除都尝试一遍
for (int i = 0; i <= cur; i++) {
if (dfs(x + rec[i], cur + 1)) return true;
if (dfs(abs(x - rec[i]), cur + 1)) return true;
//注意题目要求不出现负指数
}
return false;
}
int main() {
while (cin >> n && n) {
maxh = 0;
memset(rec, 0, sizeof(rec));
while (!dfs(1, 0)) {
memset(rec, 0, sizeof(rec));
maxh++;
//清空数据,加大约束值,重新搜索
}
cout << maxh << endl;
}
return 0;
}