题目要求乘除法的最少次数,其实就是一个数组中一开始只有一个数:1 ,每次可以从数组中取两个数(可以取同一个数)相加生成一个新数加如数组 。
那么显然这是一个迭代加深搜索,从小到大枚举深度上限 。
为了降低时间复杂度,我们要尽量的减少迭代次数,所以我们优先做加法,并且优先将最大的两个数相加,这样可以最快的接近目标 。
当然,有一个很显然的剪枝: 当每次取最大的两个数相加仍然小于n时要剪枝 。因为以最快的方式增长的话其指数是按照2的幂次增加的,所以当前最大值maxv*pow(2,maxd-d) < n 时剪枝 。
数据只有1000,打表可以0ms过 。
细节见代码:
#include<bits/stdc++.h> using namespace std; const int maxn = 1000+5; int n,maxd,a[maxn]; bool dfs(int d) { if(a[d] == n) return true; if(d == maxd) return false; int maxv = a[0]; for(int i=0;i<=d;i++) maxv = max(maxv,a[i]); if(maxv*pow(2,maxd-d) < n) return false; for(int i=d;i>=0;i--) { a[d+1] = a[d] + a[i]; if(dfs(d+1)) return true; a[d+1] = a[d] - a[i]; if(dfs(d+1)) return true; } return false; } int main() { while(~scanf("%d",&n)&&n) { a[0] = 1; for(maxd = 0; ; ++maxd) { if(dfs(0)) break; } printf("%d\n",maxd); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-10 15:17:25