【ACM】PAT.A1103 Integer Factorization【搜索】

这篇博客详细介绍了PAT A1103整数因式分解的问题,包括题目要求、解题策略和AC的C++程序实现。重点在于如何有效地寻找不超过给定限制的数的幂次和,以及在遍历过程中应用的剪枝策略,以确保解决方案的正确性和效率。
摘要由CSDN通过智能技术生成
题目链接
题目分析

题意:分解因式 – K个数 的 P次方之和 = N

数值范围: N <= 400, K <= N, 1 < P <= 7

多方案时选择基数和最大的,基数和也相同时按字典序选择最靠前的

解题思路

1、由于P确定,可以提前确定P次幂小于N 的数,用数组fac[] 保存起来
2、每次DFS()确定是否加 fac[i],形成两个分支
3、需要传的参数有:

cur: 从N递减遍历求幂次和,保证字典序
tempK: 当前已加的个数(<=K)
tempN: 当前的和
tempS: 当前已入选的底数的和

4、剪枝策略:

①、num > K 【入选的数超额】
②、tempN > N 【幂次和溢出】
③、cur <= 0 【所有数遍历完成】
④、curP次幂已>N


AC程序(C++)
/**************************
//@Author: 3stone
//@ACM: PAT-A1103
//@Time: 18/2/2
//@IDE: VS2017
***************************/
#include<cstdio>
#include<iostream>
#include<vector>
#define maxSize 1000
using namespace std;

int N, K, P, maxSum = 0;
int fac[maxSize];  //保存 key^P ,避免重复计算
vector<int> ans, temp;  //存储已选择的底数

//计算幂次值
int getK_P(int value) { 
    int t = P - 1, temp0 = value;
    while (t > 0) {
        value = temp0 * value;
        t--;
    }
    return value;
}

void init() { //初始化fac[]
    int value;
    for (int i = 1; i <= N; i++) {
        value = getK_P(i);
        if (value > N) break;
        fac[i] = value;
    }
}

//cur:当前递减到的数值
void DFS(int cur, int tempK, int tempN, int tempS) { 

    if (tempK > K || cur <= 0 || tempN > N) return; //剪枝

    if (K == tempK && tempN == N) { //满足题意
        if (tempS > maxSum) {//取最优项,判底数和是否最大
            ans = temp;
            maxSum = tempS;
        }
    }
    else {
        if (fac[cur] != 0) { //此数的P次幂小于N,即可加(剪枝)
            temp.push_back(cur);
            DFS(cur, tempK + 1, tempN + fac[cur], tempS + cur);//加入此数
            temp.pop_back();
        }
        DFS(cur - 1, tempK, tempN, tempS);// 不加此数
    }
}

int main() {
    int tempN = 0, tempK = 0, tempS = 0;// 幂次和, 已选个数,数值和
    while (scanf("%d %d %d", &N, &K, &P) != EOF) {
        memset(fac, 0, sizeof(fac));
        init();
        temp.clear(); //清空
        ans.clear();

        // 当前数,当前幂次和,已选个数,底数和
        DFS(N, tempN, tempK, tempS);

        if (ans.size() != 0) { //输出
            printf("%d = ", N);
            vector<int>::iterator flag = ans.end();
            for (vector<int>::iterator it = ans.begin(); it != flag - 1; it++) {
                printf("%d^%d + ", *it, P);
            }
            printf("%d^%d\n", *(flag - 1), P);
        }
        else {
            printf("Impossible\n");
        }
    }
    system("pause");
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值