【PAT甲级 DFS+剪枝 C++】1103 Integer Factorization (30分)

# include <iostream>
# include <vector>
# include <algorithm>
# include <cmath>
using namespace std;

int N, K, P; // 分别存放指定和、底数个数和次方数
int maxSum = -1; // 存放最大底数和
vector<int> tmp, ans; // 分别存放当前的底数组合and和最大的底数组合(和相等时选择底数大的)
vector<int> Fac; // 存放nowK的P次方

// 打表得到nowK的P次方会快很多
void getFac(){
    
    
    int board = pow(N, 1.0/P);
    for(int i = 0;i<=board;++i){
    
    
        Fac.push_back(pow(i, P));
    }
}
// nowK当前的底数(从大到小递归)、nowN当前的多项式的P次方和、nowmaxSum当前底数组合的底数和
void DFS(int nowK, int nowN, int nowmaxSum){
    
    
    // 剪枝
    if(nowK < 1 || nowN > N || tmp.size() > K) return;
    
    // 死胡同:其实在这不能叫做死胡同,应该叫做更新点,更新最佳底数组合
    // 当前底数组合的个数为K 并且 当前底数组合的P次方和等于指定数N 时更新
    if(tmp.size() == K && nowN == N){
    
    
        if(nowmaxSum > maxSum){
    
    
            ans = tmp;          // 更新最佳底数组合
            maxSum = nowmaxSum; // 更新最大底数和
        }
        return; // 在更新完当前的底数组合之后,应该回溯去找其他的底数组合,所以这也就是死胡同
    }
    // 岔路口:选或不选当前nowK
    tmp.push_back(nowK);
    DFS(nowK, nowN+Fac[nowK], nowmaxSum+nowK); // 选nowK数,因为可以有重复的nowK,所有不写nowK-1而是nowK
    tmp.pop_back();
    DFS(nowK-1, nowN, nowmaxSum); // 不选nowK数
}

int main(){
    
    
    cin >> N >> K >> P;
    getFac();
    // 从大到小去递归就可以得到从大到小的底数组合
    DFS(pow(N, 1.0/P),0,0);

    if(maxSum != -1){
    
    
        printf("%d = ", N);
        for(int i = 0;i<ans.size();++i){
    
    
            printf("%d^%d", ans[i], P);
            if(i != ans.size() - 1) 
                cout << " + ";
        }
    }
    else
        cout << "Impossible";
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/MYMarcoreus/article/details/113563277