首页 > 代码库 > UVA1374 - Power Calculus(迭代深搜+剪枝)

UVA1374 - Power Calculus(迭代深搜+剪枝)

题目链接

题意:给出x和正整数n,问最少需要几次乘除法 可以得到n = x^m

思路:其实是关于指数的操作,即从1到m最少的步数。我们可以先确定最少步数m,然后进行迭代,迭代的过程也就是判断通过相加减所得到的数可以在m次操作中等于n,如果符合,m即为最小步数,如果不符合,m++,进行下一次迭代。迭代过程中要注意剪枝,即剩余的次数如果每次都是取最大值相加还是比n小的话,就直接跳出。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

const int MAXN = 1005;
using namespace std;

int arr[MAXN];
int n, depth, num;

void init() {
    depth = 0;
    int temp = 1;
    while (n > temp) {
        temp = temp * 2; 
        depth++;
    }
}

int dfs(int cur, int d) {
    if (d >= depth) {
        if (cur == n) 
            return true;
        return false;
    }
    for (int i = num - 1; i >= 0; i--) {
        int Max = 0;
        for (int j = 0; j < num; j++) 
            Max = max(Max, arr[j]);
        if ((cur + Max) << (depth - d - 1) < n)
            return false;
        arr[num++] = cur + arr[i];
        if (dfs(cur + arr[i], d + 1))
            return true;
        num--;
        arr[num++] = cur - arr[i];
        if (dfs(cur - arr[i], d + 1))
            return true; 
        num--;
    }
    return false;
}

int main() {
    while (scanf("%d", &n) && n) {
        if (n == 1) {
            printf("0\n"); 
            continue;
        }
        init();
        while (1) {
            memset(arr, 0, sizeof(arr)); 
            arr[0] = num = 1;
            if (dfs(1, 0))
                break;
            depth++;
        }
        printf("%d\n", depth); 
    }    
    return 0;
}