1. 程式人生 > >UVA 1374 Power Calculus(迭代深搜)

UVA 1374 Power Calculus(迭代深搜)

 

題目:Power Calculus

題意:輸入正整數n(1≤n≤1000),問最少需要幾次乘除法可以從x得到xn?例如,x31需要6次: 。 計算過程中x的指數應當總是正整數(如x-3=x/x4是不允許的)。

思路:繼續IDA*,看了紫書分析,我想的是每次將得到的集合排序後才能得到最大,看了程式碼庫後,其實只需從深度d開始計算即是最大的。。。

(1)列舉搜尋深度,最大列舉深度13

(2)dfs搜尋:每次從當前深度d列舉集合中的元素,用a[d](當前集合中最大值) + 列舉a[i]  = a[d+1] 新增元素,然後繼續遞迴,還有一次相減過程,同相加一樣!直到找到,或者達到當前最大深度退出,或剪枝退出。

(3)剪枝:用當前序列最大的數乘以2^(maxd-d)之後仍小於n,則剪枝。()
---------------------
作者:GuoZLH
來源:CSDN
原文:https://blog.csdn.net/GuoZLH/article/details/55097078
版權宣告:本文為博主原創文章,轉載請附上博文連結!

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 13;//最大深度
int a[maxn+1]={1};
inline int h(int d){//求指數集合中最大的值
    int ans_max = 0;
    for(int i=0;i<=d;i++) ans_max = max(ans_max,a[i]);
    return ans_max;
}
inline bool is_fin(int d,int n){//是否達到結果
    if(a[d] == n) return true;
    return false;
}
bool dfs(int d,int maxd,int n){
    if(is_fin(d,n)) return true;//是否達到結果
    if(d == maxd) return false;//列舉深度達到上限停止
    if((h(d) << (maxd-d)) < n) return false;//剪枝:
    //列舉:從指數集合中最大的開始
    for(int i=d;i>=0;i--){
        a[d+1] = a[d] + a[i];//將集合中當前最大的依次加上較大的為新的元素
        if(dfs(d+1,maxd,n)) return true;//進行遞迴,找到返回成功
        a[d+1] = a[d] - a[i];//將集合中當前最大的依次減去較大的為新的元素
        if(dfs(d+1,maxd,n)) return true;//進行遞迴,找到返回成功
    }
    return false;
}
int solve(int n){
    if(n == 1) return 0;
    for(int maxd=1;maxd<maxn;maxd++){
        if(dfs(0,maxd,n)) return maxd;
    }
    return maxn;
}
int main()
{
    int n;
    while(scanf("%d",&n) == 1 && n) printf("%d\n",solve(n));
    return 0;
}
--------------------- 
作者:GuoZLH 
來源:CSDN 
原文:https://blog.csdn.net/GuoZLH/article/details/55097078 
版權宣告:本文為博主原創文章,轉載請附上博文連結!