题目
思路
这道题是一道用DFS进行选择的题目;
最难的点在于想到把 fac 数组预先处理出来,这样在选择的时候其实是在对 fac 数组下标所代表的数从高往低是否选择进行决策;
假设 n^p <= test, 并且此时的 n 最大,那么我们在进行选择的时候要从 考虑 n, n-1, n-2 ……1 是否应该被选择;若index代表当前在对哪个数进行选择,则 index 从 n 开始 递减到 1;
nowk是当前选择了多少个数,sum是已选的和,facsum是已选底数的和;
如果 nowk = = num &&sum == test,则说明找到一组可行解,此时将facSum 与 maxSum 进行比较,取最优值;
如果 sum >= test || nowK >= num ,说明此时已经不满足题意,可以剪枝;
紧接着就是该元素选和不选的分枝递归了;
代码
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cstring>
#include <math.h>
using namespace std;
vector<int> fac, temp, ans;//fac记录每个下标的p次方为多少,temp存储临时底数序列,ans存储最优的底数序列
int test, num, p, maxSum = -1;//test是给定数据, num代表多项式的项数, p是指数
void init(){
int sum = 0, d = 0;
while(sum <= test){
fac.push_back(sum);
sum = pow(++d, p);
}
}
//index代表当前在对哪个数进行选择,nowk是当前选择了多少个数,sum是已选的和,facsum是已选底数的和
void DFS(int index, int nowK, int sum, int facSum){
//找到一组可行解
if(nowK == num && sum == test){
//找到一组更优的解
if(facSum > maxSum){
ans = temp;
maxSum = facSum;
}
return;
}
//剪枝,回溯
if(sum >= test || nowK >= num) return;//如果此时和已经大于等于给定数或者已选择个数已经大于等于num,则已经不满足题意了
//进行分枝选择
if(index - 1 >= 0){
//选择当前数
temp.push_back(index);
DFS(index, nowK + 1, sum + fac[index], facSum + index);
temp.pop_back();
//不选当前数
DFS(index - 1, nowK, sum, facSum);
}
}
int main()
{
scanf("%d%d%d", &test, &num, &p);
//初始化fac
init();
//从高位向低位开始选择
DFS(fac.size() - 1, 0, 0, 0);
if(maxSum == -1) printf("Impossible\n");
else{
printf("%d = %d^%d", test, ans[0], p);
for(int i = 1; i < ans.size(); i ++){
printf(" + %d^%d", ans[i], p);
}
}
system("pause");
return 0;
}