PAT_A1103(DFS深搜)

                            1103 Integer Factorization (30分)

The K−P factorization of a positive integer N is to write N as the sum of the P-th power of K positive integers. You are supposed to write a program to find the K−P factorization of N for any positive integers N, K and P.

Input Specification:

Each input file contains one test case which gives in a line the three positive integers N (≤400), K (≤N) and P (1<P≤7). The numbers in a line are separated by a space.

Output Specification:

For each case, if the solution exists, output in the format:

N = n[1]^P + ... n[K]^P

where n[i] (i = 1, ..., K) is the i-th factor. All the factors must be printed in non-increasing order.

Note: the solution may not be unique. For example, the 5-2 factorization of 169 has 9 solutions, such as 12​2​​+4​2​​+2​2​​+2​2​​+1​2​​, or 11​2​​+6​2​​+2​2​​+2​2​​+2​2​​, or more. You must output the one with the maximum sum of the factors. If there is a tie, the largest factor sequence must be chosen -- sequence { a​1​​,a​2​​,⋯,a​K​​ } is said to be larger than { b​1​​,b​2​​,⋯,b​K​​ } if there exists 1≤L≤K such that a​i​​=b​i​​ for i<L and a​L​​>b​L​​.

If there is no solution, simple output Impossible.

Sample Input 1:

169 5 2

Sample Output 1:

169 = 6^2 + 6^2 + 6^2 + 6^2 + 5^2

Sample Input 2:

169 167 3

Sample Output 2:

Impossible

 

一、AC代码 

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

int ans[400+5];     //存放答案
int fac[400+5];     //存放因素n[k]
int temp[400+5];  //存放在dfs中不断更新的因素n[Nowk]
int N, K, P,Maxfac;  //169(N)=6(n[1])^2(P) + 6^2 + 6^2 + 6^2 + 5(n[k])^2,Maxfac = 29
bool juge;  //用来判断是否存在等式

//计算w的P次方
int Pow(int w){
    int ans = 1;
    for(int i=0; i<P; i++)
        ans *= w;
    return ans;
}

//打印
void Print()
{
    printf("%d = %d^%d", N,ans[1],P);
    for(int i=2; i<=K; i++)
        printf(" + %d^%d", ans[i],P);
    printf("\n");
}

//temp数组赋值给ans数组
void duplicate(int a[], int b[])
{
    for(int i=1; i<=N; i++)
        b[i] = a[i];
}

//!核心代码
void dfs(int Nowk, int index, int sum, int pl, int x)
{
    if(sum>N || Nowk>K)
        return;

    if(sum==N && Nowk==K && pl>Maxfac)
    {
        juge = true;
        duplicate(temp, ans);
        Maxfac = pl;
        return;
    }

    if(index-1 >=0)  //题目中有要求,N必须是正整数且由正整数相加,当index>1时可以继续选择
    {
        temp[x] = index;

        dfs(Nowk+1, index, sum+fac[index], pl+index, x+1);

        dfs(Nowk, index-1, sum, pl, x);
    }
}

int main(){
    int t;
    while(scanf("%d%d%d", &N, &K, &P)!=EOF)
    {
        juge = false;
        for(int i=0; i<=400; i++)
        {
            t = Pow(i);
            if(t<=N)
            {
                fac[i] = t;
            }else{
                t = i-1;
                break;
            }
        }
        dfs(0,t,0,0,1);  //此处注意初始值
        if(!juge)
            printf("Impossible\n");
        else
            Print();
    }
}
//使用<math>头文件中的pow()函数注意,double类型转为int会掉精度,所以最好自己写一个

 

二、思路

    弄清楚此题的简单逻辑框架,就能够实现最重要的dfs()函数中的代码。每次到达fac中的元素值时,比如169关于P=2的底数最大值为13,那么对于13我们就有两种选择;第一就是选择13,把13^2=169加入到sum中,并将构成此元素的底数13(n[i]^p中的n[i])加入到facsum中,我们接下来再继续选择13作为底数看是否满足要求。第二就是不选择此元素,底数-1进入递归,下一次的dfs的底数就从12开始。

    在这里为什么底数是-1呢?因为我们从最大可能的底数开始,比较容易得到最大的sumfac也就是最终的最大底数和的那一组式子构成最终的答案。

    可能到这里还会有些模糊,我们大致的框架上再继续细化。

    当我们如果选择此元素,那么递归中的参数包括Nowk,也就是我们现在是在选择式子中的第i个数(i=1,2,3...K)需要+1,代表我们选择的元素占了一个位置。参数中的index,也就是我们选择的底数,最开始是13,在下一次选择中不变仍然选入。参数中的sum,也就是现在式子中所有元素的和要使用sum = sum + fac[index]更新。参数中的pl用来记录目前的式子中的底数和,最终覆盖形成我们最后的答案Maxfac,所以要更新为pl = pl + index。

    如果我们发现加入此元素后导致sum>N 或者 Nowk>K 时,代表无答案,那么返回上一级到达下一个选项--不选择。不选择此元素,那么底数-1,sum、Nowk、pl都不变(没有加入元素当然不变),temp的下标也不变(如果不构成答案,那么当前位置可覆盖)。

 

三、收获

    1. vector复习

    2. dfs复习

    3. 小细节,pow()函数赋值给int会导致精度丢失,计算的最终值错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值