1103. Integer Factorization (30) -- 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 = n1^P + … nK^P

where ni (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 122 + 42 + 22 + 22 + 12, or 112 + 62 + 22 + 22 + 22, 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 { a1, a2, … aK } is said to be larger than { b1, b2, … bK } if there exists 1<=L<=K such that ai=bi for ibL

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

http://www.patest.cn/contests/pat-a-practise/1103

// 21分 各种运行超时
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <queue>

using namespace std;

#define N 20

int n , k , p;

bool flag ;
vector<int> ans ;

int numP(int num) // num的p次方
{
    int sums = num ;
    for(int i = 1 ; i < p ; i++)
    {
        sums *= num ;
    }
    return sums;
}

int sumv(vector<int> vv) // 求和
{
    int sums = 0 ;
    for(int i = k-1 ;i >= 0 ; i --)
    {
        sums += vv[i];
    }
    return sums;
}

bool cmp(vector<int> v1,vector<int> v2)
{
    if(sumv(v1) > sumv(v2))
        return true;
    else if (sumv(v1) == sumv(v2))
    {
        for(int i = k-1 ;i >= 0 ; i --)
        {
            if(v1[i] > v2[i])
                return true;
            if(v1[i] < v2[i])
                return false;
        }
    }
    return false;
}

vector<int> ansT ;

bool dfs(int n , int step)
{
    int i;
    if(n < 0 || step > k)
        return  false;
    if(step == k  && n == 0)
    {
        if(flag == false)
        {
            flag = true;
            for(i = 0 ;i < k;i++)
            {
                ans.push_back(ansT[i]);
            }
        }else{
            if( cmp(ansT,ans) )
            {
                ans.clear();
                for(i = 0 ;i < k;i++)
                {
                    ans.push_back(ansT[i]);
                }
            }
        }
        return true;
    }else{
        for(i = 1 ;i <= n ; i++)
        {
            int num = numP(i);
            ansT.push_back(i);
            dfs(n-num , step+1);
            if((int)ansT.size() > 0 )
                ansT.pop_back();
        }
    }
    return false;
}


int main()
{
    //freopen("in.txt","r",stdin);
    int i;
    while(scanf("%d%d%d",&n,&k,&p) != EOF)
    {
        int tmpn = n ;
        ans.clear();
        ansT.clear();
        flag = false;
        dfs(n,0);
        if(flag)
        {
            printf("%d = %d^%d",tmpn,ans[k-1],p);
            for(i = k-2;i>=0;i--)
            {
                printf(" + %d^%d",ans[i],p);
            }
        }else{
            printf("Impossible");
        }
        printf("\n");
    }
    return 0 ;
}
// 27分代码
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <queue>

using namespace std;

#define N 20

int n , k , p;

int ansSum;
vector<int> ans ;

int numP(int num) // num的p次方
{
    int sums = num ;
    for(int i = 1 ; i < p ; i++)
    {
        sums *= num ;
    }
    return sums;
}

int sumv(vector<int> vv) // 求最后结果的和
{
    int sums = 0 ;
    for(int i = k-1 ;i >= 0 ; i --)
    {
        sums += vv[i];
    }
    return sums;
}

bool cmp(vector<int> v1,vector<int> v2) // 比较结果的大小
{
    for(int i = k-1 ;i >= 0 ; i --)
    {
        if(v1[i] > v2[i])
            return true;
        if(v1[i] < v2[i])
            return false;
    }
    return false;
}

vector<int> ansT ;

bool dfs(int n , int step)
{
    int i;
    if(n < 0 || step > k)
        return  false;
    if(step == k && n != 0)
        return false;
    if(step == k  && n == 0)
    {
        if(ansSum == -1)
        {
            ansSum = 0 ;
            for(i = 0 ;i < k;i++)
            {
                ans.push_back(ansT[i]);
                ansSum += ansT[i];
            }
        }else{
            int sumT = sumv(ansT);
            if( sumT > ansSum ) // 和 大
            {
                ansSum = sumT ;
                ans.clear();
                for(i = 0 ;i < k;i++)
                {
                    ans.push_back(ansT[i]);
                }
            }else if(sumT == ansSum && cmp(ansT,ans)) // 和 相等
            {
                ans.clear();
                for(i = 0 ;i < k;i++)
                {
                    ans.push_back(ansT[i]);
                }
            }
        }
        return true;
    }else{
        for(i = 1 ;i <= n ; i++)
        {
            int num = numP(i);
            if(num > n) // 这里比n大 则直接 return 
                return false;
            int len = (int)ansT.size();
            if(len > 0 && num < ansT[len-1]) // 跳过该元素 保证后一个元素比前一个元素大于等于
                continue;
            ansT.push_back(i);
            dfs(n-num , step+1); // dfs 下一个
            if((int)ansT.size() > 0) // 回溯 pop出去
                ansT.pop_back();
        }
    }
    return false;
}


int main()
{
    //freopen("in.txt","r",stdin);
    int i;
    while(scanf("%d%d%d",&n,&k,&p) != EOF)
    {
        int tmpn = n ;
        ans.clear();
        ansT.clear();
        ansSum = -1 ;
        dfs(n,0);
        if(ansSum != -1)
        {
            printf("%d = %d^%d",tmpn,ans[k-1],p);
            for(i = k-2;i>=0;i--)
            {
                printf(" + %d^%d",ans[i],p);
            }
        }else{
            printf("Impossible");
        }
        printf("\n");
    }
    return 0 ;
}
// ac代码
#include <iostream> 
#include <cstdio> 
#include <vector> 
using namespace std;  

int num[21];  
int maxSum = 0;  
vector<int> res;  
vector<int> vec;  

/** start 表示开始的数 k 为个数 n 为要求的数 sum 为当前已经求得的和 */
void dfs(int start, int k, int n, int sum)
{  
    if (k == 0){  
        if (n == 0){  
            if (sum >= maxSum){  
                res = vec;//只用记录最后一组答案就好,因为从数学的角度看,这是最佳的 
                maxSum = sum;  
            }  
        }  

    }  
    else{  
        if (n > 0){  
            for (int i = start; i < 21; ++i){  
        // 显然 n < num[i] 就不满足了
                if(n - num[i] < 0) //剪枝,没有这个判断测试点5过不了 
                    break;  
                vec.push_back(i);  
                dfs(i, k - 1, n - num[i], sum + i);  

        vec.pop_back();  // 回溯 直接弹出最后一个数
            }  
        }  
    }  
}  
int main(void)
{  
    int n, k, p;  
    scanf("%d%d%d", &n, &k, &p); 
  // num[i] 表示 i^p 这样就直接不用pow了
    for (int i = 1; i < 21; ++i){    
        num[i] = 1;  
        for (int j = 0; j < p; ++j){  
            num[i] *= i;  
        }  
    }  
  // dfs(int start, int k, int n, int sum) 
    dfs(1, k, n, 0);  

    if (res.empty())  
        printf("Impossible\n");  
    else{  
        printf("%d = ", n);  
        printf("%d^%d", res[k - 1], p);  
        for (int i = k - 2; i >= 0; --i){  
            printf(" + ");  
            printf("%d^%d", res[i], p);  
        }  
        printf("\n");  
    }  
    return 0;  
}  

ac代码学习:http://blog.csdn.net/apie_czx/article/details/48415197

你可能感兴趣的:(1103. Integer Factorization (30) -- dfs 回溯 待解决)