PAT(甲级)1103 Integer Factorization (30point(s))

题目

题目链接

思路

这道题是一道用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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值