题意
题意:输入正整数n(1≤n≤1000),问最少需要几次乘除法可以从x得到xn?例如,x^31需要6次 (计算过程中x的指数应当总是正整数)
思路
类似”埃及分数”问题, 一个巨大的搜索树, 定义一个搜索的最大深度限制maxd,每次搜索都要在maxd深度之内进行,如果没有找到解,就继续增大maxd,直到成功找到解
剪枝 : 若当前最大数乘2^(maxd-d)之后仍小于n, 即剩下的一直乘2都达不到n
关于迭代加深搜索 IDA*:
使用条件 : 在一些搜索问题中,使用普通的DFS可能会让你把时间浪费在深度非常大而且答案不是最优的搜索过程上,甚至有的时候DFS搜索的深度是无穷的,而BFS虽说理论上可以避免这种情况,却又无法满足题目的某些需求,或者无法实现。仔细思考一下这个例子,它有着两个特征:一是它是个最优解问题,最优的答案深度最小;二是它搜索时可能会达到极大的深度,而这样的答案是没用且费时的。
参考链接
IDDFS(迭代加深搜索)基础题两则
埃及分数问题-迭代加深搜索与IDA*算法
“埃及分数”问题浅谈对迭代加深搜索的理解
附:
参考代码链接
AC代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#define mst(a) memset(a, 0, sizeof(a))
using namespace std;
const int maxn = 15;
int s[maxn];
int f( int d ){
int m = -1;
for( int i = 0; i <= d; i++ )
m = max(m, s[i]);
return m;
}
bool win( int d, int n ){
if( s[d] == n ) return true;
return false;
}
bool dfs( int d, int maxd, int n ){
if( win(d, n) ) return true;
if( d == maxd ) return false;
if( f(d) << (maxd-d) < n ) return false; //乐观估计剪枝
for( int i = d; i >= 0; i-- ){
s[d+1] = s[d] + s[i]; //乘
if( dfs(d+1, maxd, n) ) return true;
s[d+1] = s[d] - s[i]; //除
if( dfs(d+1, maxd, n) ) return true;
}
return false;
}
int solve( int n ){
if( n == 1 ) return 0;
s[0] = 1;
for( int maxd = 1; ; maxd++ )
if( dfs(0, maxd, n) )
return maxd;
}
int main()
{
int n;
while( scanf("%d",&n) && n ){
mst(s);
printf("%d
",solve(n));
}
return 0;
}