题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=41552
本题不算太难,但我刚开始的时候居然理解错了。那句“问最少需要几次乘除法可以从X得到X^n?“,从这句话中你一定要能理解他是从一开始,每次从之前的数据中抽出两个数来进行运算,之前我就一直在纠结,X他又没给我,我怎么求?额,智商不够没办法,努力吧。好废话不扯了,进入正题。
解题思路:
本题我们要求的是最短路径,一想到求最短路径无非就是BFS或者就是迭代加深搜,由于本题数据还是有些大,所以用迭代加深搜,外加启发式函数。迭代加深搜都是固定思维,我们先来说说启发式函数吧。就是估计以后的每次运算都取最大值假如还低于N,那么就返回false。其实是关于指数的操作,即从1到m最少的步数。我们可以先确定最少步数m,然后进行迭代,迭代的过程也就是判断通过相加减所得到的数可以在m次操作中等于n,如果符合,m即为最小步数,如果不符合,m++,进行下一次迭代。迭代过程中要注意剪枝,即剩余的次数如果每次都是取最大值相加还是比n小的话,就直接跳出。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxans = 13;
int n,ans[maxans+1];
bool dfs(int d,int maxd){
if(ans[d] == n)return true;//找到答案
if(d == maxd)return false;
int maxv = ans[0];
for(int i = 1;i <= d; i++)maxv = max(maxv,ans[i]);//找出之前的最大值,用来写启发式函数
if((maxv << (maxd-d)) < n) return false;//如果之后的全取最大值仍然小于n,则返回假
for(int i = d;i >= 0; i--){
ans[d+1] = ans[d] + ans[i];
if(dfs(d+1,maxd))return true;
ans[d+1] = ans[d] - ans[i];
if(dfs(d+1,maxd))return true;
}
return false;
}
int solve(){
if(n == 1)return 0;
ans[0] = 1;
for(int maxd = 1;maxd < maxans; maxd++){
if(dfs(0,maxd))return maxd;//迭代
}
return maxans;
}
int main(){
while(scanf("%d",&n) == 1 && n){
printf("%d\n",solve());
}
}