pat甲级1103

有技巧地枚举所有选数的可能,形成二叉树,再通过递归实现深度优先遍历,每次到达叶子节点就进行一次结果比较,确定是否更新最终结果。算法笔记上写的很好,一个数只能选一次的情况,与一个数可以选多次,稍微更改即可。备选数的最大值为P次根号下N,从最大值开始选会更快。另外就是预处理的技巧,遍历时涉及到重复计算一个数的P次方,提前用一个数组保存下来,可以节省时间。

#include <cstdio>
#include <vector>
#include <cmath>

using namespace std;

int N, K, P, ans_sum=0;
vector<int> ans, temp;

bool better_check();
//已选好ct个数,下一个备选数为num
void proc(int num, int ct, int sum_p, int temp_sum, double pow_p[]);

int main(){
    scanf("%d%d%d", &N, &K, &P);
    int roof=1;
    while(pow(roof, P)<N){
        roof++;
    }
    double pow_p[roof+1];
    for(int i=1; i<=roof; i++){
        pow_p[i] = pow(i, P);
    }
    proc(roof, 0, 0, 0, pow_p);
    if(ans.empty()) printf("Impossible");
    else{
        printf("%d =", N);
        for(int i=0; i<K; i++){
            printf(" %d^%d", ans[i], P);
            if(i<K-1) printf(" +");
        }
    }
    return 0;
}

bool better_check(){
    for(int i=0; i<K; i++){
        if(ans[i]!=temp[i]) return ans[i]<temp[i];
    }
}

void proc(int num, int ct, int sum_p, int temp_sum, double pow_p[]){
    if(ct==K && sum_p==N){
        if(temp_sum>ans_sum){
            ans_sum = temp_sum;
            ans = temp;
            return;
        }
        else if(temp_sum==ans_sum && better_check()){
            ans_sum = temp_sum;
            ans = temp;
            return;
        }
        return;
    }
    if(num<1 || ct==K || sum_p>N) return;
    temp.push_back(num);
    proc(num, ct+1, sum_p+pow_p[num], temp_sum+num, pow_p);
    temp.pop_back();
    proc(num-1, ct, sum_p, temp_sum, pow_p);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值