# 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;
}
【PAT甲级 DFS+剪枝 C++】1103 Integer Factorization (30分)
猜你喜欢
转载自blog.csdn.net/MYMarcoreus/article/details/113563277
今日推荐
周排行