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

ac20170214

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <algorithm>
#include <sstream>
#include <list>
#include <stack> 
#include <map> 
#include <set> 
#include <iterator> 
#include <unordered_map>

using namespace std;

#define INF 0x7fffffff

typedef long long int LL;

const int N = 404;

int n, k, p;

int maxVal;
int pows[N];

int maxSum;
vector<int> res;

vector<int> ans;

void dfs(int cur,int ceng,int sumNow,int sum)
{
    if(cur > maxVal || ceng > k || sumNow > n)
        return;

    if(sumNow == n && ceng == k)
    {
        /*for(int i=0;i<(int)ans.size();i++)
            cout << ans[i] << " ";
        cout << endl;*/

        if(sum >= maxSum)
        {
            maxSum = sum;
            res = ans; 
        }
    }

    for(int i=cur;i<=maxVal;i++)
    {
        if(sumNow + pows[i] > n || pows[i] > n)
            break;

        ans.push_back(i);

        dfs(i,ceng + 1, sumNow + pows[i],sum + i);

        ans.pop_back();
    }

}

int main()
{
    //freopen("in.txt", "r" ,stdin);

    while( scanf("%d%d%d", &n, &k, &p) != EOF)
    {
        for(int i=1;i<=n;i++)
        {
            int powTmp = 1; 
            for(int j=0;j<p;j++)
                powTmp *= i;
            int tmp = powTmp;
            if(tmp <= n)
            {
                maxVal = i;
                pows[i] = tmp;
            }
            else
                break;
        }

        res.clear();
        ans.clear();
        maxSum = -1;

        dfs(1,0,0,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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值